質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

6回答

15173閲覧

【JS】なぜ、55000 * 1.08 = 59400.00000000001 になるのでしょうか

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

4グッド

3クリップ

投稿2016/09/21 06:53

編集2016/09/21 07:18

Windows7 で Chrome 53.0.2785.116 の最新版を使用しています。

JSで自動で税込みの価格を表示しようと下記のように記述しました。

<!doctype html> <html> <head> <meta charset="utf-8"> <title>test</title> <script type="text/javascript"> const TAX = 1.08; var result = 55000 * TAX; console.log(result); </script> </head> <body> </body> </html>

計算結果が 59400.00000000001 になります。

試しに他の値(40000, 1200, 100, 648, 550, 550000)を入れてみましたが、丸め問題は発生しません。

単純に小数点以下を切り捨てるなら、下記のように Math.floor() を使えば想定通りの結果が返ってきます。

<!doctype html> <html> <head> <meta charset="utf-8"> <title>test</title> <script type="text/javascript"> const TAX = 1.08; var result = Math.floor(55000 * TAX); console.log(result); </script> </head> <body> </body> </html>

なぜ、55000 だけうまく計算されないのでしょうか?

Math.floor()を使うことで問題は解決しておりますので、計算されない理由を教えてくださいm(__)m


追記

1500, 2500, 3500, 4500, 5500, 6500, 7500, 8500, 9500 を試してみましたが、下記は丸め問題が発生するようです。どういうことでしょう(?_?)

3500 * 1.083780.0000000000005
6500 * 1.087020.000000000001
7500 * 1.088100.000000000001

ozwk, oriduru, ystke, SHIKI_MONAKO👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

iwamoto_takaaki

2016/09/21 07:16

丸め誤差が出ないようにしたいのか。出る理由を知りたいのか。 答える方向性がまるで違うのではっきりさせておいたほうが良いと思います。
guest

回答6

0

IEEE 754

原因は ECMAScript 2016 (ES7) が採用する IEEE 754-2008 の演算精度にあります。
この掲示板で説明できる文量を超えていて私も他人に説明できるほどの理解はしていない為、下記リンクを参考にしてみてください。
最も詳しいのはおそらく [IEEE Std 754™-2008 (PDF)] です。

浮動小数点演算と整数演算

仕組み上、浮動小数点演算は誤差が生じるので誤差を生じさせたくない場合は整数演算を使うのが一般的です。

JavaScript

1function setTax (number) { 2 return number * 108 / 100; 3} 4 5console.log(setTax(3500)); // 3780 6console.log(setTax(6500)); // 7020 7console.log(setTax(7500)); // 8100 8console.log(setTax(55000)); // 59400

Math.floor()を使うことで問題は解決しておりますので、計算されない理由を教えてくださいm(__)m

質問文にある事例では、Math.floor() で期待通りに動作しているように見えますが、誤差の仕組みを私もはっきりと理解しているわけではない為、「誤差範囲が常に +1 未満で収まるか」どうかが分かりません。

Re: gununu さん

投稿2016/09/21 08:03

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

think49

2016/09/21 08:04

回答内容を吟味している内に回答が付いて解決済になっていました。失礼しました。
退会済みユーザー

退会済みユーザー

2016/09/21 08:19 編集

回答ありがとうございます。 IEEE754について調べようとしていたので、とても助かります^^ これから拝見して理解を深めたいと思います。 整数演算についてのコードも参考になりました。 回答ありがとうございましたm(__)m
guest

0

ベストアンサー

JavaScriptなど多くの言語で、浮動小数点数にIEEE 754という形式を使っています。

この形式は、1の位以下も1/2の位、1/4の位と2進法になっているので、「1.08」のような10進法では割り切れる小数でも、IEEE 754では正確に表せない、ということが多く発生します。

Rubyのように有理数や10進数型が提供されているのであればそちらで計算すればいいのですが、JavaScriptの場合はそういうわけにもいかないので、「整数の範囲内で計算する」とか「適当な単位で丸める」などの対応が必要となります。

投稿2016/09/21 07:35

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/21 07:58 編集

回答ありがとうございます。 どこの記事が失念しましたが、エクセルの計算結果を例にコンピュータは少数を計算できないので、浮動小数点数や固定少数点数を使って表しているという記事を読んでいて、丸め問題があるということは知っておりましたが、少数第○○桁まで正確に表す場合だけかと思っておりました(^^;) 私の知識不足でした>< IEEE754について詳しく調べます。 回答ありがとうございました。
guest

0

小数点以下の計算をする限り必ず誤差が生じます。
一度、整数化してから最後に割り戻してやるとよいかもしれません

javascript

1var a=1.08; 2var b=55000; 3console.log(a*b);//誤差がでる 4var n=a.toFixed()==a?1:Math.pow(10,a.toString().match(/\.(.+)/)[1].length); //この場合nは100 5console.log((a*n)*b/n);//誤差がない 6

投稿2016/09/21 07:37

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/21 07:56

回答ありがとうございます。 整数化して計算する方法もあるんですね^^ 参考なりました。ありがとうございます。
guest

0

Math.floor で解決したそうですが、誤差の問題だと round にしないとおかしなことになるケースもあります

javascript

10.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 2//0.9999999999999999

floor では切り捨てられるので、ちょっと多いのじゃなくてちょっと少ないのケースが来ると数値が変わってきます

.9999999・・・が 1.08 を掛けるケースだと起きないのかもしれませんけど

投稿2016/09/21 08:00

lazex

総合スコア604

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/21 08:17

回答ありがとうございます。 安直に Math.floor を使って切り捨てましたが、足りないもケースもあるんですね>< IEEE754について調べて理解を深め、切り捨てるかどうか適切に判断したいと思います。 回答ありがとうございましたm(__)m
guest

0

なぜ誤差が出るかという質問として、計算と誤差を熟読してください。由々しき問題ではあります。

投稿2016/09/21 07:16

編集2016/09/21 07:18
Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/21 07:38

回答サイトありがとうございます^^ 参考サイトを読んで理解したいと思います。
guest

0

1.08 をかけるのは、消費税 8% を含む金額の計算ではないでしょうか?
var z = x + ( x * 8 / 100 );
として、税額部分 ( x * 8 / 100 ) に誤差があるようなら丸めるのが良いと思います。

税率が変更になった場合も確認する必要がありそうなので、回答してみました。

投稿2016/09/29 08:52

AkiraPenguin

総合スコア51

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問