🧮

Swift Decimal はどこまで表せるか

2023/12/24に公開

結果

正確に表すのは39桁程度が限界(128ビット)
雑でよければ166桁程度が限界(内容のある39桁 + 0で埋める127桁)

Decimalは何?

Intの64ビットを超えた値を使える
浮動小数的に言うと、仮数部が128ビット。指数部が8ビット。ただし指数部が表す値nは10^nとして結果に反映される。
仮数部が128ビットなので10進数39桁程度まで正確に扱える。それを超えると正確さは落ちるが指数部の8ビットを使い、10進数166桁程度(39 + 127)まで扱える。
最高は10進数166桁程度なので Double の308桁よりは小さい。よって Double の代わりになるものではない(感想)。
指数部は負もあるので0.02のようなものも出来る。0.02は仮数部2 指数部-2

直感的には

  1. 表したい値を10進数表記する
  2. 最後の部分に0が連続していたらその個数を指数部の値とする
  3. 残りを仮数部とする

となる。

指数部にあたるのが exponent
仮数部にあたるのが significand

import Foundation
var a: Decimal = 1200
print(a.exponent) //2
print(a.significand) //12
import Foundation
var a: Decimal = 0.012
print(a.exponent) //-3
print(a.significand) //12

significand (厳密には _mantissa )は UInt16 の8個分ある。つまり128ビット。保存形式は普通に2進数。53を 0101 0011 みたいにはしない。128ビットをフル活用。

exponent の限界に挑戦する

挑戦↓

import Foundation
var a: Decimal = 123
for _ in 0..<200 {
    print(a.magnitude) //総合結果
    print(a.exponent)   
    print(a.significand)
    print()
    a *= 10
}

結果は↓

123
0
123

1230
1
123

12300
2
123

(省略)

12300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
125
123

123000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
126
123

1230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
127
123

NaN
127
NaN

NaN
127
NaN

0の個数は127が限界

significand の限界に挑戦する

挑戦↓

import Foundation
var a: Decimal = 123
for _ in 0..<200 {
    print(a.magnitude) //総合結果
    print(a.exponent)   
    print(a.significand)
    print()
    a *= 7
}

結果は↓

123
0
123

861
0
861

6027
0
6027

(省略)

268609168246990981690445407088721378189
0
268609168246990981690445407088721378189

1880264177728936871833117849621049647320
1
188026417772893687183311784962104964732

13161849244102558102831824947347347531200
2
131618492441025581028318249473473475312

92132944708717906719822774631431432718000
3
92132944708717906719822774631431432718

39桁が限界
それを超えると有効桁数はそのままで exponent を増やすことで対応する。

Discussion