【问题标题】:NSDecimalNumber issuesNSDecimalNumber 问题
【发布时间】:2015-02-17 19:33:16
【问题描述】:

在我的 iOS swift 应用程序中,我从网络收到一些 json,其中包含一些代表货币的双精度值。它看起来像这样:

[{"Amount": 5.0},{"Amount":-26.07},{"Amount": 4}, ...etc]

我将它们转换为 Double,然后尝试将这些值作为 Swift“Double”输入到 NSDecimalNumber 的构造函数中,如下所示:

let amount = NSDecimalNumber(double: amountAsDouble)

我在使用这种方法时遇到了问题,因为我创建的 NSDecimalNumber 经常会包含一个不同的数字,该数字经过小数点后 16 位。

let amount = NSDecimalNumber(double: -15.97)
println(amount)

这将返回 -15.970000000000004096

我不想要这个,我想要 -15.97。 谢谢,

【问题讨论】:

    标签: ios swift nsdecimalnumber


    【解决方案1】:

    我最近亲身经历了这个。我最终使用 NSNumberFormatter 来获得正确的小数位。

    let currFormatter = NSNumberFormatter()
        currFormatter.numberStyle = .DecimalStyle
        currFormatter.roundingIncrement = 0.01
        currFormatter.minimumFractionDigits = 2
        currFormatter.maximumFractionDigits = 2
    
    let doubleAmount = currFormatter.numberFromString(amountAsDouble) as NSNumber!
    let amount = doubleAmount as Double
    println(amount)
    

    【讨论】:

      【解决方案2】:

      这里有个提示:如果你使用 NSJSONSerializer,带小数点的数字实际上会为你转换成 NSDecimalNumber。 NSDecimalNumber 是 NSNumber 的子类。所以你在做什么:你有一个非常好的 NSDecimalNumber,将值四舍五入到 double,然后尝试将 double 转回 NSDecimalNumber。只需检查您所拥有的确实是一个 NSDecimalNumber,如果是,则不要进行转换。

      【讨论】:

      • 这是一个有用但有点误导的答案。 (NS)JSONSerialization 将数字转换为 NSNumber,而不是 NSDecimalNumber。您可以使用 NSNumber 的 decimalValue 属性来获取 (NS)Decimal。
      【解决方案3】:

      Double 存储有 18 位十进制数字,您对此无能为力,它就是这样工作的。

      在这里阅读:http://en.wikipedia.org/wiki/Double-precision_floating-point_format

      但是,在屏幕上显示值时,您可以像这样使用NSNumberFormatter

      let amountInDouble: Double = -15.970000000000004096
      
      let formatter = NSNumberFormatter()
      formatter.numberStyle = .DecimalStyle
      formatter.roundingIncrement = 0.01
      formatter.maximumFractionDigits = 2
      
      let amountAsString = formatter.stringFromNumber(NSNumber(double: amountInDouble))
      
      if let amountAsString = amountAsString {
          println(amountAsString) // -15.97
      }
      

      【讨论】:

        【解决方案4】:

        这是因为中间双精度表示会导致问题。

        您应该将字典中的值作为NSString 对象并使用+ decimalNumberWithString: 方法进行转换而不会丢失精度。迅速:

        let amount = NSDecimalNumber(string: amountAsString)
        

        【讨论】:

        • 我会试试这个,然后回来标记为答案或提出另一个问题。谢谢
        • 好的,所以我在将 json 的值转换为字符串时遇到了一些麻烦。我试图做的实际上只是保持之前的 Double 值并改用它。到目前为止一切顺利,但我担心在某些情况下,Double 值会失去它的精度。
        • 这似乎不起作用 - 它仍然会导致精度损失。 NSDecimalNumber(string: "9277.235") -> 返回 9277.2350000000001
        【解决方案5】:
             let amount = NSDecimalNumber.init(value: -15.97)
        
            let roundValue = amount.rounding(accordingToBehavior: NSDecimalNumberHandler(roundingMode: .bankers, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false))
        
            print(roundValue)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多