NSDecimalNumber的数学完整性

时间:2018-01-17 19:31:09

标签: ios nsdecimalnumber

我使用数字除以10 ^ 30

我可能会添加存储在NSDecimalNumber s中的值1000000000000000和5000000000000000。

我担心的是,我认为我已经多次看到,在添加或减去这些值时,会进行不正确的数学运算。

这是一种可能性,还是NSDecimalNumbers在数学的完整性方面非常合理。

2 个答案:

答案 0 :(得分:2)

在回答您的问题时,Decimal / NSDecimalNumber提供的数学运算合理,问题可能在于:

  1. 计算可能超出这些十进制格式的容量(如rob mayoff所述)。例如,这是有效的,因为我们在38位尾数内:

    let x = Decimal(sign: .plus, exponent: 60, significand: 1)
    let y = Decimal(sign: .plus, exponent: 30, significand: 1)
    let z = x + y
    
      

    1,000,000,000,000,000,000,000,000,000,001,000,000,000,000,000,000,000,000,000,000

    但这不会:

    let x = Decimal(sign: .plus, exponent: 60, significand: 1)
    let y = Decimal(sign: .plus, exponent: 10, significand: 1)
    let z = x + y
    
      

    1,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000

  2. 或者,它可能就是您如何实例化这些十进制值,例如提供浮点数而不是使用Decimal(sign:exponent:significand:)NSDecimalNumber(mantissa:exponent:isNegative:)初始值设定项:

    例如,这很好用:

    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    
    let x = Decimal(sign: .plus, exponent: 30, significand: 1)
    print(formatter.string(for: x)!)
    

    结果是:

      

    1,000,000,000,000,000,000,000,000,000,000

    但是这些不会,因为你提供的浮点数在精度上有较低的限制:

    let y = Decimal(1.0e30)
    print(formatter.string(for: y)!)
    
    let z = Decimal(1_000_000_000_000_000_000_000_000_000_000.0)
    print(formatter.string(for: z)!)
    

    这两个都导致:

      

    1,000,000,000,000,000,409,600,000,000,000

  3. 有关浮点运算的更多信息(以及为什么在浮点类型中无法完美捕获十进制数),请参阅floating-point arithmetic

    your other question中,您会问以下原因:

    let foo = NSDecimalNumber(value: 334.99999).multiplying(byPowerOf10: 30)
    

    制备:

      

    334999990000000051200000000000000

    这与我在上面第2点中概述的基本问题相同。浮点数不能准确表示某些小数值。

    请注意,您的问题与以下Decimal版本相同:

    let adjustment = Decimal(sign: .plus, exponent: 30, significand: 1)
    let foo = Decimal(334.99999) * adjustment
    

    这也产生:

      

    334999990000000051200000000000000

    但如果您提供字符串或指数以及尾数/重要值,您将获得所需的结果,因为这些将准确表示为Decimal / NSDecimalNumber

    let bar = Decimal(string: "334.99999")! * adjustment
    let baz = Decimal(sign: .plus, exponent: -5, significand: 33499999) * adjustment
    

    这两者都产生:

      

    334999990000000000000000000000000

    底线,不要向DecimalNSDecimalNumber提供浮点数。使用字符串表示或使用指数和尾数/有效数表示,使用浮点数时不会看到这些奇怪的偏差。

答案 1 :(得分:0)

  

我使用数字除以1 ^ 30

好消息,那么,因为1 ^ 30 = 1.也许你的意思是10 ^ 30?

无论如何,根据NSDecimalNumber class reference

  

实例可以表示任何可以表示为尾数x 10 ^指数的数字,其中尾数是长度为38位的十进制整数,指数是-128到127之间的整数。