→2022/11/6 浮動小数点演算
>Kirari1192 (途中だがセクションを作るため保存) |
>Kirari1192 |
||
390行目: | 390行目: | ||
日本語のウェブサイトでも今はUTF-8が主流ナリが過去にはShift-JISやEUC-JPが主流だった時代もあり、エンコーディングというのは現代では非常に重要な概念になっているのは間違いないですを | 日本語のウェブサイトでも今はUTF-8が主流ナリが過去にはShift-JISやEUC-JPが主流だった時代もあり、エンコーディングというのは現代では非常に重要な概念になっているのは間違いないですを | ||
=== 2022/11/6 | === 2022/11/6 浮動小数点数と浮動小数点演算 === | ||
コンピュータでの小数の取り扱いはそう簡単な話ではないナリ | コンピュータでの小数の取り扱いはそう簡単な話ではないナリ<br> | ||
例えば0.1という数を考えるナリ<br> | |||
5倍すれば0.1×5で0.5<ref>念の為に書いておきますが、何のとんちや引っ掛けもありません。単純な算数の話です</ref>、それは分かるよね? | |||
でもコンピュータの世界ではそうは行かないナリ | |||
(Kotlin) | |||
>>> 0.1f.toDouble() | |||
res12: kotlin.Double = 0.10000000149011612 | |||
>>> 0.1f.toDouble()*5 | |||
res13: kotlin.Double = 0.50000000745058060 | |||
コンピュータ上での0.1の扱いが強調されるように少し加工しているナリが<ref>KotlinなのかJavaのせいか不明だが、そのままやるとちゃんと0.5が出てくるので32ビット浮動小数点数(単精度)を64ビット(倍精度)に変換した</ref>、浮動小数点の世界では0.1を含む様々な小数点以下の値を厳密に保管できないですを | |||
これは浮動小数点の内部的な表現と2進数と10進数の変換に起因しているナリ<br> | |||
コンピュータに載っているCPUは{{wpl|ja:IEEE 754|IEEE 754}}形式に従って小数を表現していますを<br> | |||
細かいことに関してはMuyopediaのリンク先を見て欲しいナリが、大まかには符号部、指数部、仮数部の3つで成り立っていますを<br> | |||
0.1は2進数表現をすると循環節<ref>ある周期で永遠に繰り返すこと</ref>が発生するナリ そのため一定の桁数で表せないことから上で示したように誤差が発生しますを | |||
これが倍精度(64ビット)IEEE 754表現での0.1ですを | |||
(Kotlin) | |||
>>> 0.1.toRawBits().toString(2).padStart(64, '0') | |||
res22: kotlin.String = 0011111110111001100110011001100110011001100110011001100110011010 | |||
この数の仮数部は<code>1001100110011001100110011001100110011001100110011010</code>ナリ<br> | |||
ほぼ最後まで1001の繰り返しになっていることが分かると思うナリ これはいけない | |||
同様の理由で、大きな整数も浮動小数点数で表現できないですを<br> | |||
1234567890430440987654321という数を例に取るナリ<br> | |||
上が倍精度浮動小数点数、下が本来の2進数表現とそのビット数ナリ | |||
(Kotlin) | |||
>>> "1234567890430440987654321".toDouble().toRawBits().toString(2).padStart(64, '0') | |||
res45: kotlin.String = 0100010011110000010101101110000011110011011110111101011101111001 | |||
>>> "1234567890430440987654321".toBigInteger().toString(2) | |||
res47: kotlin.String = 100000101011011100000111100110111101111010111011110010001111111110111100010110001 | |||
>>> "1234567890430440987654321".toBigInteger().toString(2).length | |||
res48: kotlin.Int = 81 | |||
倍精度浮動小数点数の仮数部は52ビットなので、その仮数ビットに収まりきらない程の桁を入れようとしていたことが分かるナリ<br> | |||
これを<strong>桁落ち</strong>と言いますを 桁落ちは誤差の原因になるナリ | |||
同じ現象を引き起こす例として、大きな数と非常に小さい小数を足す場合があるナリ | |||
(Kotlin) | |||
>>> 43044.toDouble()+0.000000000005 | |||
res4: kotlin.Double = 43044.00000000001 | |||
浮動小数点数は整数部と小数部を自由自在に融通できて便利という面がある一方、小数点では循環節が発生して表現しきれないことがあるなど一長一短ナリ<br> | |||
通常の使い方では倍精度浮動小数点数で十分ナリが、言語によっては任意精度演算も可能なので必要に応じて使い分けることを切に望む。 | |||
==== プログラミング講座について ==== | |||
恒心教リッピング路線の原状復帰の目途が立ったので今回で終了ナリ 皆様との出会いに感謝<br> | |||
質問はいつでも受付けているナリ ではさよなら法政二中 またどこかでお会いしましょう | |||
== 脚注 == | == 脚注 == | ||
<references /> | <references /> |