はじめに
- 筆者が疑問に思って検証した結果を書いたもので、double型のすべてを記したものではない
- この記事内の「出力」というのは、Console.WriteLineの表示結果のこと
- 「16進数出力」は、BitConverter.DoubleToInt64Bits()を使用して、doubleのビットの状態を表示したもの
各種定数のビット
定数 |
16進数出力 |
0 |
0x0000000000000000 |
1 |
0x3FF0000000000000 |
MinValue |
0xFFEFFFFFFFFFFFFF |
MaxValue |
0x7FEFFFFFFFFFFFFF |
Epsilon |
0x0000000000000001 |
NaN |
0xFFF8000000000000 |
0.99… どのくらいまでなら正確に保持できるか
結論
- コード上で表記:0.9999999999999999
- 16進数の場合:0x3FEFFFFFFFFFFFFF
検証:コード上で直接入力して出力した結果
- 9の数が17以上になると、1.0となってしまう。
- 0x3FEFFFFFFFFFFFFFは、1.0 未満だが、出力すると 1.0 となる。
9の数 |
コード上の表記 |
10進数出力 |
16進数出力 |
1 |
0.9 |
0.9 |
0x3FECCCCCCCCCCCCD |
2 |
0.99 |
0.99 |
0x3FEFAE147AE147AE |
略 |
|
|
|
15 |
0.999999999999999 |
0.999999999999999 |
0x3FEFFFFFFFFFFFF7 |
16 |
0.9999999999999999 |
1.0 |
0x3FEFFFFFFFFFFFFF |
17 |
0.99999999999999999 |
1.0 |
0x3FF0000000000000 |
18 |
0.999999999999999999 |
1.0 |
0x3FF0000000000000 |
検証:1.0から徐々に小さくしていった場合
- BitConverter.Int64BitsToDouble()を使用して、整数から実数に変換し出力
- 0x3FEFFFFFFFFFFFFFは、1.0 未満だが、出力すると 1.0 となる。
元の整数 |
実数出力 |
0x3FF0000000000000 |
1.0 |
0x3FEFFFFFFFFFFFFF |
1.0 |
0x3FEFFFFFFFFFFFFE |
1.0 |
0x3FEFFFFFFFFFFFFD |
1.0 |
0x3FEFFFFFFFFFFFFC |
1.0 |
0x3FEFFFFFFFFFFFFB |
0.999999999999999 |
0x3FEFFFFFFFFFFFFA |
0.999999999999999 |
doubleで正確に保持可能な整数の最大値
結論
- 9007199254740992
- 16進数:0x20000000000000
検証:long→double→longの順番でキャスト
- 0x20000000000001 は、longに戻した後 0x20000000000000 になってしまう。
各出力結果
元のlong値 |
代入後のdouble値(16進数出力) |
キャスト後のlong値 |
0x1FFFFFFFFFFFFF |
0x433FFFFFFFFFFFFF |
0x1FFFFFFFFFFFFF |
0x20000000000000 |
0x4340000000000000 |
0x20000000000000 |
0x20000000000001 |
0x4340000000000000 |
0x20000000000000 |
ToStringのフォーマット
double.Epsilon を小数表記で出力する方法
結論:桁プレースホルダーを使用する
"0.####・・・"の、"#"が338個並んだフォーマットを使用する。
検証:書式指定子を使用した場合
- 小数表記で表示されず、指数表記になる。
- 精度指定子では99桁が限界、100桁以上は"F100"のように出力されてしまう。
- 補足:C,E,Pは、そもそも目的が違うので、ここには載せていません。
書式指定子 |
出力結果 |
F99 |
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
G99 |
4.9406564584124654E-324 |
N99 |
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
R99 |
4.94065645841247E-324 |
検証:桁プレースホルダーを使用した場合
- 桁プレースホルダーとは、"0.####"のように書いたフォーマットのこと
#の数 |
出力結果 |
337 |
0.000(略)00049406564584125 |
338 |
0.000(略)000494065645841247 |
339 |
0.000(略)000494065645841247 |