2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コンピュータ特有の演算誤差

Posted at

この記事の執筆者

プログラミング学習を始めて、5ヶ月ほど。Vue.js Typescript Railsを学習中の大学生.

きっかけ

Typescriptの参考書を学習中に下記のようなコードを書いたら予期しない結果になったため調べてみることにした。参考書には誤差が出る理由等は詳しく書かれていなかった。

let price = 12500
let tax = 1.1
let withTax = price * tax

console.log("金額" + price )
console.log(`税込価格は、${withTax}`)

結果

金額12500
税込価格は、13750.000000000002

上記のコードは定価である12,500円に対して税率である0.1を加えたものである。
期待していた結果としては下記のようなもの

12,500 * 1.1 = 13,750


コンピューター特有の演算誤差

このような予期しない演算結果が出るのは、どうやら調べてみるとJavascriptだけではないようだ。

コンピュータの内部では2進数で計算されているため!

らしいのだが2進数について完全に忘れていたため(おそらく高校で少しだけやった...)まずは2進数について調べてみた。

2進数

そもそも2進数とは 0と1で表された値

10進数 2進数
0 0
1 1
3 11
4 100
5 101
6 110
7 111
0.1 0000 0000 . 00001 1001 1001 1001 1001...

どうやら 0.1は2進数で表すと0000 0000 . 0001 1001 1001 1001 1001 1001 .....以下無限に続くよう(循環小数)

このように小数の一部では2進数で表すと循環小数になってしまう。よってそれを扱った演算では計算が意図しないものになることがわかった。

解決方法

let price = 12500
let tax = 1.1 * 10
let withTax = (price * tax) / 10

console.log("金額" + price )
console.log(`税込価格は、${withTax}`)

結果

金額12500
税込価格は、13750

上記のコードでは小数を10倍して整数に直す(2進数では整数の形だと循環小数にならないため)
そして、計算した結果を10で割ることによって結果を出している。
他のやり方もあるそうなのでできなかった方は以下を参考にしてください。

### まとめ
万能に見えていたコンピュータでも1と0しか把握できないことで意図しない計算結果を生む可能性があることがわかった。複雑な計算になればなるほどこのような箇所は見落としがちなので十分に注意したい。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?