- ベストアンサー
数値の掛け算の不具合について
下記のようなページで <HTML> <HEAD> <script language="JavaScript"> <!-- function calc() { document.f.t3.value = eval(document.f.t1.value) * eval(document.f.t2.value); return true; } //--> </script> </HEAD> <BODY bgcolor="#FFFFFF"> <form name="f"> <input type="text" name="t1"> × <input type="text" name="t2" onkeyup="calc()"> = <input type="text" name="t3"> </form> </BODY> </HTML> 一番目のテキストフォームと2番目のテキストフォームに任意の数値を入力したら3番目のテキストフォームに掛け算された結果が表示されるというプログラムで、一番目に10.07と入力し、2番目に11を入力して掛け算をさせると110.77000000000001となってしまいます。 本当の結果は110.77なのですが。。。。 どなたか、原因、対処法をご存知の方、ご教授ください。 よろしくお願い致します。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> ちなみに、掛け算だけこのような問題がでるのでしょうか? > 割り算などでは問題は起きないのでしょうか? これは、実数が浮動小数点で表現されていることに起因する問題ですから、演算の 種類に限らず発生する問題です。 手元の NN4.7x で確認したのですが、例えば、以下のような計算が期待通りにいきません。 1.01 + 1.1 1.01 - 1.1 12.3 / 0.3 > これは、ひどいですよね。Javascriptは。 先ほども書いた通り、浮動小数点を扱うものは全てこの問題を抱えています。 JavaScript がひどいとしたら、実数をフォーマットして出力してくれる仕組み (C だったら printf() 関数とか)を標準で用意していないことです。 まあ、みんなが欲しくなるものは、誰かが作っていたりします。例えば、参考URLの ページなんかが。
その他の回答 (4)
- xruz
- ベストアンサー率50% (72/143)
こんにちは、xruzです。 誤差が生ずるのは2進数で演算しているためです。 回避方法(小数点以下が2桁の場合): <HTML> <HEAD> <script language="JavaScript"> <!-- function calc() { document.f.t3.value = ((parseFloat(document.f.t1.value) * 100.0) * parseFloat(document.f.t2.value)) / 100.0 ; return true; } //--> </script> </HEAD> <BODY bgcolor="#FFFFFF"> <form name="f"> <input type="text" name="t1"> × <input type="text" name="t2" onkeyup="calc()"> = <input type="text" name="t3"> </form> </BODY> </HTML> がんばってくださいね(^:^i
お礼
ご回答ありがとうございます。 >document.f.t3.value = ((parseFloat(document.f.t1.value) * 100.0) * parseFloat(document.f.t2.value)) / 100.0 ; parseFloatを使って、100をかけ、あとで100で割るという作業をするのですね。
- A__
- ベストアンサー率47% (22/46)
割り算でも誤差が生じる場合があるみたいです。 整数の足し算でも誤差が生じる場合があります。 桁数が多いとなるみたいです。
お礼
お返事有難うございます。 下記のa-kumaさんのようになるのですね。 実際に試してみましたら、 1.01-1.1=09000000000000008 となりました。 (私はWINのIE6です)
- A__
- ベストアンサー率47% (22/46)
alert(10.07*11) が 110.77000000000001 になりました。 小数の場合、数字の最後の部分が 0001 と 9999 の ような誤差が発生する場合がある。 小数の掛け算なら計算結果の小数の桁が予想できるから、 10.07*11 なら、小数は第2位までだと分かっているから 計算結果の数字から、コンマがあれば、コンマの右の 2つの数字までをコンマ無しで抜き出して、11077 小数第3位が9であれば1を足す。 最後にコンマを戻して 11077 にする。 10.07*0.145 なら、小数は第5位までだと分かっているから 計算結果の数字から、コンマがあれば、コンマの右の 5つの数字までをコンマ無しで抜き出して、146014 小数第6位が9であれば1を足す。 最後にコンマを戻して 1.46015 にする。 こんな感じでも出来そうです。
お礼
貴重なご意見有難うございます。 なるほど、999の場合と001のパターンで場合わけするのですね。 ちなみに、掛け算だけこのような問題がでるのでしょうか? 割り算などでは問題は起きないのでしょうか?
- Blackwingls
- ベストアンサー率44% (138/313)
こんばんわぁ、Blackwinglsです。 これは恐らく丸め処理のせいでしょう。 ブラウザではこの丸め処理の誤差部分まで表示してしまうようなので、11.1+111.1 が正しい計算結果が得られない、という話をどこかで聞いた覚えがあります。 結局、作成者側で何桁まで必要か考えて四捨五入するしかないようです。 <script language="JavaScript"> <!-- function calc() { var a = eval(document.f.t1.value) * eval(document.f.t2.value) var b = Math.round(a * 100) / 100 document.f.t3.value = b return true; } //--> </script> というのではどうでしょうか? 2桁まで求めるようにしています。 ではでは(@^^)/~~~
お礼
ご回答ありがとうございます。 たぶん、誤差の問題だろうとは思っていましたが。。 これは、ひどいですよね。Javascriptは。 2桁ですか。。 もっとほしいときもあるのですが、危険ですよね。 その都度考えるようにします。
お礼
ご回答ありがとうございます。 printf関数を利用すればよいのですね。 printfは書式付の書き出しという意味ですか? ただ、printf()関数をどういった形で利用すればよいのでしょうか? すみません。プログラムの基本をわかってないものですから。