代码之家  ›  专栏  ›  技术社区  ›  Oleg Gordiichuk

NSDecimalNumber到UInt64转换问题

  •  0
  • Oleg Gordiichuk  · 技术社区  · 6 年前

    我实现了以下功能:

    func number(for cof: UInt8, limit: UInt64) -> UInt64 {
        let decimalResult = (1 + Decimal(cof)/255) * Decimal(limit) / 1000
        return NSDecimalNumber(decimal: decimalResult).uint64Value
    }
    

    cof :

    number(for: 0, gasLimit: 21000) // Result is 21
    

    cof公司

    number(for: 128, gasLimit: 21000) // Result is 0 
    

    调试128后 价值观。

     let decimalResult = (1 + Decimal(gasPriceCoef)/255) * Decimal(gasLimit) / 1000 // Result is 31.5411764705882352941176470588235294116
    

    问题是,当我把十进制值转换成UInt64时,我得到0

    2 回复  |  直到 6 年前
        1
  •  3
  •   OOPer    6 年前

    uint64Value 是的财产 NSNumber NSDecimalNumber .

    但据我测试,尾数部分超过 UInt64 0 . 例如, 31.5411764705882352941176470588235294116 在中表示为31541176470588235294117647058823529411610^(-38) N小数 ,和 315411764705882352941176470588235294116 UInt64.max . (*1)

    为了避免这种行为(*2),可以在将十进制值转换为之前对其进行四舍五入 .

    func number(for cof: UInt8, limit: UInt64) -> UInt64 {
        var decimalResult = (1 + Decimal(cof)/255) * Decimal(limit) / 1000
        var roundedResult = Decimal()
        NSDecimalRound(&roundedResult, &decimalResult, 0, NSDecimalNumber.RoundingMode.plain)
        return NSDecimalNumber(decimal:  roundedResult).uint64Value
    }
    print(number(for: 128, limit: 21000)) //->32
    

    (*1)实际行为似乎有点复杂,参见

    (*2)一旦标记为已解决,此行为肯定是一个错误。另见上文马丁R的另一条评论。

        2
  •  1
  •   SomaMan    6 年前

    这是因为十进制值不是整数;uninit64值与此无关。你可以用原语-

    let result = (1 + Double(cof) / 255) * Double(limit) / 1000
    return UInt64(result)