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
190
プログラミングで小数計算すると なんで誤差が発生するのか?
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
360
ふりかえりでふりかえることしかできなかったジュニアチームが、次の打ち手を出せるチームになるのにやったこと
kumagoro95
3
1.3k
Githubのアクティビティ履歴からチームの健康状態を知る(Findy Teams使ってみた)
kumagoro95
0
480
導入事例を通じて理解するドメイン駆動設計
kumagoro95
0
290
The Assembly ~ directly controlling CPU ~
kumagoro95
0
350
非エンジニアがドメイン駆動設計(DDD)について説明してみる。
kumagoro95
1
330
カンタン楽しいマイコンの世界
kumagoro95
0
89
Featured
See All Featured
Scaling GitHub
holman
458
140k
Designing for Performance
lara
604
68k
The Invisible Side of Design
smashingmag
297
50k
4 Signs Your Business is Dying
shpigford
180
21k
Designing the Hi-DPI Web
ddemaree
280
34k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
664
120k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
13
1.8k
Agile that works and the tools we love
rasmusluckow
327
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
Thoughts on Productivity
jonyablonski
67
4.3k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
355
29k
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
ご清聴ありがとうございました