NSDecimalNumber的数学完整性 [英] Mathematical integrity of NSDecimalNumber

查看:102
本文介绍了NSDecimalNumber的数学完整性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的数字除以10 ^ 30

I'm using numbers divided by 10^30

我可能会添加存储在 NSDecimalNumber 秒。

I may be adding values like 1000000000000000 and 5000000000000000 stored in NSDecimalNumbers.

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

My concern is that I think I've seen a few times, when adding or subtracting these values, incorrect math being done.

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

Is that a possibility or are NSDecimalNumbers pretty sound in terms of the integrity of their math.

推荐答案

在回答你的问题时, Decimal / <$ c $提供的数学算法c> NSDecimalNumber 是合理的,问题可能在于:

In answer to your question, the math offered by Decimal/NSDecimalNumber is sound, and the problem probably rests in either:


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

  1. The calculations might exceed the capacity of these decimal formats (as outlined by rob mayoff). For example, this works because we're within the 38 digit mantissa:

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,000

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,000,000

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


  • 或者,它可能就是你的样子实例化这些十进制值,例如提供浮点数而不是使用十进制(符号:指数:有效数字:) NSDecimalNumber(尾数:指数:isNegative:)初始值设定项:

    例如,这样可以正常工作:

    For example, this works fine:

    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

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

    但这些不会,因为你供应一个浮点数,它的精度下限受到限制:

    But these won't, because you're supplying a floating point number which suffers lower limits in precision:

    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

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


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

    For more information on floating-point arithmetic (and why certainly decimal numbers cannot be perfectly captured in floating-point types), see floating-point arithmetic.

    你的另一个问题,你问为什么以下:

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

    产生:

    334999990000000051200000000000000

    334999990000000051200000000000000

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

    This is the same underlying issue that I outlined above in point 2. Floating point numbers cannot accurately represent certain decimal values.

    注意,您的问题与以下十进制 r相同结束:

    Note, your question is the same as the following Decimal rendition:

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

    这也产生:


    334999990000000051200000000000000

    334999990000000051200000000000000

    但如果您提供字符串或者字符串,您将获得所需的结果指数和尾数/有效,因为它们将准确地表示为十进制 / NSDecimalNumber

    But you will get the desired result if you supply either a string or a exponent and mantissa/significant, because these will be accurately represented as a Decimal/NSDecimalNumber:

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

    这两个产生:


    334999990000000000000000000000000

    334999990000000000000000000000000

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

    Bottom line, do not supply floating point numbers to Decimal or NSDecimalNumber. Use string representations or use the exponent and mantissa/significand representation and you will not see these strange deviations introduced when using floating point numbers.

    这篇关于NSDecimalNumber的数学完整性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆