NSDecimalNumber的数学完整性 [英] Mathematical integrity of NSDecimalNumber
问题描述
我使用的数字除以10 ^ 30
I'm using numbers divided by 10^30
我可能会添加存储在 NSDecimalNumber $ c中的值1000000000000000和5000000000000000 $ C>秒。
I may be adding values like 1000000000000000 and 5000000000000000 stored in NSDecimalNumber
s.
我担心的是,我认为我已经看过几次,在添加或减去这些值时,会进行不正确的数学运算。
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:
-
计算结果可能超过这些十进制格式的容量(由rob mayoff概述)。例如,这是有效的,因为我们在38位尾数内:
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屋!