Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
プログラミングで小数計算すると なんで誤差が発生するのか? くまごろー ?
Slide 2
Slide 2 text
このテーマを選んだいきさつ ● プログラミング学習を進めてると、「double/float型で小数計算すると誤差が 発生する」という現象に遭遇する ● 参考書では「正確に計算したいときはBigDecimal型を使いましょう」とか言 われる 問1 そもそも、プログラミングで小数計算するとなんで誤差が発生するの? 問2 なんでBigDecimal型で計算すると誤差が発生しないの?
Slide 3
Slide 3 text
1 誤差が出るってどういうこと?
Slide 4
Slide 4 text
double/float型で計算すると → 答えは「0.2」のはずなのに、誤差が生じる double num1 = 1.2; double num2 = 1.0; System.out.println(num1 - num2); //0.19999999999999996
Slide 5
Slide 5 text
なぜこうなるのか? Q A コンピュータは2進数で計算している
Slide 6
Slide 6 text
● 「0」と「1」という2個の数字を使って数を表す ● その桁の数値が「2」になると桁上がりする 2進数って? 10進数 2進数 1 1 2 10 3 11 4 100 4桁目 3桁目 2桁目 1桁目 8 4 2 1 例:2進数の「1111」を 10進数に直すと... → 8+4+2+1 = 15 になる
Slide 7
Slide 7 text
2進数での小数の表し方 1 1 1 . 1 1 1 1 100 10 1 1/10 1/100 1/1000 1/10000 〇「111.1111」という数字があるとする これが10進数表記だったら・・・ <各桁の重み>
Slide 8
Slide 8 text
2進数での小数の表し方 1 1 1 . 1 1 1 1 4 2 1 1/2 1/4 1/8 1/16 〇「111.1111」という数字があるとする では、2進数だったら? 2進数の「111.1111」を10進数に直すと → (4+2+1) + (0.5 + 0.25 + 0.125 + 0.0625) = 7.9375 2の倍数の分母を持つ分数でないと表せない
Slide 9
Slide 9 text
2 誤差はどのように発生しているのか
Slide 10
Slide 10 text
ケース1:循環小数 double num1 = 1.2; double num2 = 1.0; System.out.println(num1 - num2); //0.19999999999999996 → 「0.2」は2進数で表せない (2進数だと「0.001100110011...」循環小数に)
Slide 11
Slide 11 text
double num1 = 0.1234; double num2 = 0.000000000000000004321; System.out.println(num1 + num2); //0.1234 ケース2:情報落ち → double/float型は浮動小数点数(桁数が有限)なので、 正規化が行われる(切り捨てられる)
Slide 12
Slide 12 text
浮動小数点数とは ↓のような指数表記で小数を表記する方法。 例:2進数の-0.0001の場合(10進数だと0.0625) - -3 - 0.1 × 2 符号 仮数 指数 → 表記できる桁数が増える
Slide 13
Slide 13 text
浮動小数点数とは - - 3 - 0.1 × 2 符号 仮数 指数 符号 (1Bit) 指数 (11Bit) 仮数 (52Bit) 〇 double型(64ビット)の場合 → 仮数が52ビット以上だと、切り捨てられる
Slide 14
Slide 14 text
3 なんでBigDecimalを使うと 誤差が生じないの?
Slide 15
Slide 15 text
● 「整数×10のマイナス乗」という式で数値を表現 BigDecimalの仕組み BigDecimalは、次のように値を保持している -scale unscaledValue×10 ● 整数は小数と違い、2進数でも(何進数でも)全ての数値を表す ことができる。 10進数「1.2」の場合... -1 12 × 10
Slide 16
Slide 16 text
ご清聴ありがとうございました