-1

I thought the whole point of the Decimal type was arbitrary precision arithmetic. (Or rather I thought that Decimal supported arbitrary precision as well as supporting base-10 arithmetic.)

However, an example I ran into while looking at somebody's question lead me to believe that it does have a limit. Consider this code:

let string = "728509129536673284379577474947011174006"

if var decimal = Decimal(string: string) {
    print("string \n'\(string) as a Decimal = \n'\(String(describing:decimal))'")
} else {
    print("error converting '\(string)' to a decimal")
}

That outputs

string 
'728509129536673284379577474947011174006 as a Decimal = 
'728509129536673284379577474947011174000'

It looks like the last digit gets lost. I tried various other values, and they all start showing zeros at that last digit (It looks like the low-order digit gets truncated to zero when the value contains 39 decimal digits.)

Is that documented somewhere?

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Ok, why the downvote? – Duncan C Jul 23 '23 at 13:59
  • Please read this: https://en.wikipedia.org/wiki/Double-precision_floating-point_format – Luuk Jul 23 '23 at 14:09
  • 1
    "I thought the whole point of the Decimal type was arbitrary precision arithmetic." That's not correct. The point of Decimal is to store and operate on values in base 10. What you're looking for is usually called BigInt, and will likely come to swift-numerics eventually: https://github.com/apple/swift-numerics/issues/5 For current work, see https://github.com/apple/swift-numerics/blob/biginteger/Sources/BigIntModule/BigInt.swift – Rob Napier Jul 23 '23 at 15:07
  • Ok, didn't state that correctly. I thought that Decimal was supposed to provide both base 10 math AND arbitrary precision. – Duncan C Jul 23 '23 at 15:26
  • 1
    @Luuk, Decimal is different from Double. I am well familiar with the precision limitations on types like Double and Float. – Duncan C Jul 23 '23 at 15:27

1 Answers1

3

Decimal is the bridged version of NSDecimalNumber.

An object for representing and performing arithmetic on base-10 numbers that bridges to Decimal; ...

Its representation is also documented in NSDecimalNumber:

An instance can represent any number that can be expressed as mantissa x 10^exponent where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127.

That is a bit inaccurate, since the _mantissa property does not actually store 38 decimal digits, but 128 bits.

In any case, you could say that the "maximum precision" of Decimal is 38 digits (or sometimes 39 digits depending on the mantissa), in the same sense that Double has a "maximum precision" of 15 digits (or sometimes 16 digits depending on the mantissa).

When you try to parse a number that is more precise than Decimal can handle, you can see that the precision is lost:

Decimal(string: "3402823669209384634633746074317682114551") // 40 digits
// results in    3402823669209384634633746074317682114550
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Sweeper, thanks. That answers my question very clearly. (Voted and accepted) – Duncan C Jul 23 '23 at 15:28
  • I guess I knew that Decimal was bridged from NSDecimalNumber at one point. Pity the docs don't say that. The docs for NSDecimalNumber **do** say that it's bridged to Decimal, but not the other way around (ad as you quoted, the NSDecimalNumber docs give info about precision.) – Duncan C Jul 23 '23 at 15:31