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
210
プログラミングで小数計算すると なんで誤差が発生するのか?
kumaGoro95
April 26, 2021
Tweet
Share
More Decks by kumaGoro95
See All by kumaGoro95
昭和の職場からアジャイルの世界へ
kumagoro95
1
530
DDDやってみたら 実装以前の領域での学びが深かった話
kumagoro95
13
8.3k
要件定義で得た学び・気づき
kumagoro95
4
2.4k
メンバーのわかりませんはチームが成長するチャンス.pdf
kumagoro95
1
380
ふりかえりでふりかえることしかできなかったジュニアチームが、次の打ち手を出せるチームになるのにやったこと
kumagoro95
3
1.4k
Githubのアクティビティ履歴からチームの健康状態を知る(Findy Teams使ってみた)
kumagoro95
0
530
導入事例を通じて理解するドメイン駆動設計
kumagoro95
0
340
The Assembly ~ directly controlling CPU ~
kumagoro95
0
370
非エンジニアがドメイン駆動設計(DDD)について説明してみる。
kumagoro95
1
350
Featured
See All Featured
The Cult of Friendly URLs
andyhume
78
6.3k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Designing for humans not robots
tammielis
250
25k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
50
2.4k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
15
1.1k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
28
2k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.1k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.3k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
7
610
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
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
ご清聴ありがとうございました