Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
プログラミングで小数計算すると なんで誤差が発生するのか?
Search
kumaGoro95
April 26, 2021
0
200
プログラミングで小数計算すると なんで誤差が発生するのか?
kumaGoro95
April 26, 2021
Tweet
Share
More Decks by kumaGoro95
See All by kumaGoro95
DDDやってみたら 実装以前の領域での学びが深かった話
kumagoro95
14
8.2k
要件定義で得た学び・気づき
kumagoro95
4
2.4k
メンバーのわかりませんはチームが成長するチャンス.pdf
kumagoro95
1
370
ふりかえりでふりかえることしかできなかったジュニアチームが、次の打ち手を出せるチームになるのにやったこと
kumagoro95
3
1.3k
Githubのアクティビティ履歴からチームの健康状態を知る(Findy Teams使ってみた)
kumagoro95
0
500
導入事例を通じて理解するドメイン駆動設計
kumagoro95
0
300
The Assembly ~ directly controlling CPU ~
kumagoro95
0
350
非エンジニアがドメイン駆動設計(DDD)について説明してみる。
kumagoro95
1
340
カンタン楽しいマイコンの世界
kumagoro95
0
92
Featured
See All Featured
Unsuck your backbone
ammeep
669
57k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
GitHub's CSS Performance
jonrohan
1030
460k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.5k
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
GraphQLとの向き合い方2022年版
quramy
44
13k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
YesSQL, Process and Tooling at Scale
rocio
169
14k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.6k
Why Our Code Smells
bkeepers
PRO
335
57k
Keith and Marios Guide to Fast Websites
keithpitt
410
22k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
111
49k
Transcript
プログラミングで小数計算すると なんで誤差が発生するのか? くまごろー ?
このテーマを選んだいきさつ • プログラミング学習を進めてると、「double/float型で小数計算すると誤差が 発生する」という現象に遭遇する • 参考書では「正確に計算したいときはBigDecimal型を使いましょう」とか言 われる 問1 そもそも、プログラミングで小数計算するとなんで誤差が発生するの? 問2 なんでBigDecimal型で計算すると誤差が発生しないの?
1 誤差が出るってどういうこと?
double/float型で計算すると → 答えは「0.2」のはずなのに、誤差が生じる double num1 = 1.2; double num2 = 1.0;
System.out.println(num1 - num2); //0.19999999999999996
なぜこうなるのか? Q A コンピュータは2進数で計算している
• 「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 になる
2進数での小数の表し方 1 1 1 . 1 1 1 1 100
10 1 1/10 1/100 1/1000 1/10000 〇「111.1111」という数字があるとする これが10進数表記だったら・・・ <各桁の重み>
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の倍数の分母を持つ分数でないと表せない
2 誤差はどのように発生しているのか
ケース1:循環小数 double num1 = 1.2; double num2 = 1.0;
System.out.println(num1 - num2); //0.19999999999999996 → 「0.2」は2進数で表せない (2進数だと「0.001100110011...」循環小数に)
double num1 = 0.1234; double num2 = 0.000000000000000004321; System.out.println(num1 +
num2); //0.1234 ケース2:情報落ち → double/float型は浮動小数点数(桁数が有限)なので、 正規化が行われる(切り捨てられる)
浮動小数点数とは ↓のような指数表記で小数を表記する方法。 例:2進数の-0.0001の場合(10進数だと0.0625) - -3 - 0.1 × 2 符号
仮数 指数 → 表記できる桁数が増える
浮動小数点数とは
- - 3 - 0.1 × 2 符号 仮数 指数 符号 (1Bit) 指数 (11Bit) 仮数 (52Bit) 〇 double型(64ビット)の場合 → 仮数が52ビット以上だと、切り捨てられる
3 なんでBigDecimalを使うと 誤差が生じないの?
• 「整数×10のマイナス乗」という式で数値を表現 BigDecimalの仕組み BigDecimalは、次のように値を保持している -scale unscaledValue×10 • 整数は小数と違い、2進数でも(何進数でも)全ての数値を表す ことができる。 10進数「1.2」の場合...
-1 12 × 10
ご清聴ありがとうございました