プログラムにはRubyを使用する
桁落ち
1 | printf("%.20g\n",1.1-1.0) |
1.1-1.0
を10進数で考えると、0.1
であるが、コンピュータは2進数で扱っている(データを保持している)ので、2進数で考える必要がある。0.1
を2進数に直すと、0.00011_00110_011...
(0011
が続く)となる。また、上記プログラムより、(1.1-1.0)
はFloat型である。ここで、Rubyのドキュメントによると、RubyのFloat型はC言語のdouble型であるとわかる。IEEE754より、倍精度浮動小数点数の仮数部は52ビットであるので、先の無限小数を52ビットで丸める必要がある。小数点以下52桁までで最近接偶数方向丸めをおこなうと、仮数部は.00011_00110_01100_11001_10011_00110_01100_11001_10011_00110_10
になる。これを10進数に直すと、.10000_00000_00000_08881_7
となり、小数点以下20桁で表すと、0.10000_00000_00000_08882
になるので、プログラムの実行結果と一致する。
情報落ち
1 | printf("%.20g\n",1.0+0.00000_00000_00000_9) |
1.00000_00000_00000_9
を2進数で表すと、1.00000_00000_00000_00000_00000_00000_00000_00000_00000_00001_00000...(無限小数)
となる。これも問題aと同様に52ビットに丸める必要があるので、丸めると仮数部は.00000_00000_00000_00000_00000_00000_00000_00000_00000_00001_00
となる。10進数で表すと1.00000_00000_00000_88817
となり、これを小数点以下20桁で表すと、1.00000_00000_00000_8882
になる。よってプログラムの実行結果と合致する。
丸め誤差
1 | printf("%.20g %.20g\n",7*0.1,7.0/10) |
プログラムの実行結果から掛ける数が2の累乗の場合に乗算と除算の結果が一致していることがわかる。これは割ったり掛けたりする数を2進数に直したときに小数点以下52ビット以内の有限小数となるため、誤差が生じない。よって、乗除算の結果が一致する。ただし、計算途中で丸められた場合はその限りではない。