質問: 角度を扱う計算プログラムをJavaScriptで開発しています。 角度は度分秒単位で結果を表示しています。 90°25 ́44′′ という感じに表示しています。 秒単位の小数点以下は四捨五入して表示しているのですが、計算結果が循環小数の場合だと、計算結果が電卓の結果と異なってしまいます。 電卓で 1/3*3 という計算を行うと 1 という結果になります。循環小数は加味しない結果になっているのでしょうか。 しかし、JavaScriptの場合、 0.99999999999....... という結果になってしまいます。 秒の結果が電卓だと 15.5′′ だとしても、 JavaScriptの場合だと 15.4999999999....′′ となってしまい、四捨五入すると結果が異なってしまいます。 循環小数を加味しない計算結果を求めるにはどうすれば良いでしょうか?
回答: ### 浮動小数点演算 JavaScriptの基本仕様(ECMAScript)では浮動小数点演算を **IEEE 754** に準拠しており、小数を伴う演算で正確な値を出すことが出来ません。 ですので、小数演算で正確な値を出す場合には文字列で数式を与えて、内部的に整数演算で処理する事で値を割り出すようなギミックが必要になります。 * eval-calculation.js - JSFiddle とはいえ、毎回上のような文字列処理を行うのはコストが高くつくので、通常は整数演算してから10の乗数で除算して対応します。 ``` console.log(0.6 * 3); // 1.7999999999999998 console.log(10 * 0.6 * 3 / 10); // 1.8 ``` ### 循環小数 > > 1/3*3 > > という計算を行うと 1 という結果になります。循環小数は加味しない結果になっているのでしょうか。 > > > JavaScript は循環小数も解釈しません。 この計算式であれば、次のように計算順を書き換えてやる対策が一般解となります。 ``` console.log(1*3/3); // 1 ``` それでも、`1/3*3 === 1` になるようなコードを書くとするなら、先程と同様に文字列で数式を渡し、内部的に計算順を入れ替えてやるギミックが必要になるでしょう。 **(2017/09/19 21:12追記)** eval-calculation-0.9.2.js で除算に先んじて乗算するように処理を変更しました。 * eval-calculation.js: 計算式の文字列を評価する eval-calculation-0.9.1.js 当時でも正常に動作しているように見えますが、最近のブラウザは `0.3333333333333333 * 3=== 1` が成立するようです。 というわけで、airulove さんがどの実装(ブラウザ等)で `1/3*3` を "0.99999999999......." と評価されたのか、気になるところです。 Re: airulove さん