🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

例外処理

例外処理(Exception handling)とは、プログラム実行中に異常が発生した場合、通常フローから外れ、例外として別の処理を行うようにデザインされたプログラミング言語構造です。

Q&A

解決済

2回答

876閲覧

JS代入演算子の処理桁が変動してしまう

NYzyanai

総合スコア2

JavaScript

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

例外処理

例外処理(Exception handling)とは、プログラム実行中に異常が発生した場合、通常フローから外れ、例外として別の処理を行うようにデザインされたプログラミング言語構造です。

0グッド

0クリップ

投稿2021/02/14 09:33

前提・実現したいこと

JavaScriptで、変数の中の値を「0.01」づつ減らしたいと考えています。
その為、変数名 -= 0.01;
という文を書いたのですがなぜか3回目の実行で変数が「0.009999999999999」だけ減らされる処理になってしまいます。

◆この現象が起きている理由(JavaScriptやビット演算のルール上発生しているのか?自分のコードの書き方で発生してしまっているのか?)
◆この現象が起きてしまったときにどんな言葉で検索をかけて原因を調べれば良かったのか?

の2つをしりたいです。

発生している問題・エラーメッセージ

想定外処理のためエラーメッセージはなし consoleを転記します 演算前の変数の価:7 index.html:16 演算後の変数の価:6.99 index.html:34 実行回数:1 index.html:14 演算前の変数の価:6.99 index.html:16 演算後の変数の価:6.98 index.html:34 実行回数:2 index.html:14 演算前の変数の価:6.98 index.html:16 演算後の変数の価:6.970000000000001 index.html:34 実行回数:3 index.html:14 演算前の変数の価:6.970000000000001 index.html:16 演算後の変数の価:6.960000000000001 index.html:34 実行回数:4 index.html:14 演算前の変数の価:6.960000000000001 index.html:16 演算後の変数の価:6.950000000000001 index.html:34 実行回数:5 index.html:14 演算前の変数の価:6.950000000000001 index.html:16 演算後の変数の価:6.940000000000001 index.html:34 実行回数:6 index.html:14 演算前の変数の価:6.940000000000001 index.html:16 演算後の変数の価:6.9300000000000015 index.html:34 実行回数:7

該当のソースコード

JavaScript

1<!DOCTYPE html> 2<html> 3 <head> 4 <meta charaset="UTF-8"> 5 <!--コンストラクタ作りの練習--> 6 7 <script> 8 //ここfunctionでコンストラクタを宣言する 9 function Pen(color,length){ 10 this.color=color; //代入されたcolor要素(ひとつめの要素)をプロパティにする的な 11 this.length=length; 12 //functionっていうプロパティをメソッドって読んでいる 13 this.draw=function(){ 14 console.log("演算前の変数の価:" + this.length); 15 this.length -= 0.01; 16 console.log("演算後の変数の価:" + this.length); 17 } 18 } 19 20 //んでコンストラクタの宣言がおわったから実際にオブジェクトをつくってみる 21 var penR= new Pen("red",5); 22 var penG= new Pen("green",15); 23 var penB= new Pen("Blue",7); 24 25 var pen=penR; 26 var countstroke=0 27 28 //んでストロークって何? 29 function stroke(){ 30 pen.draw(); //メソッドだから関数。()がいる 31 document.getElementById("color").textContent=pen.color; 32 document.getElementById("length").textContent=pen.length; 33 countstroke += 1; 34 console.log("実行回数:" + countstroke); 35 } 36 37 function pickR(){pen=penR}; 38 function pickG(){pen=penG}; 39 function pickB(){pen=penB}; 40 41 </script> 42 43 </head> 44 <body> 45 <button onclick="pickR()">赤を選ぶ</button> 46 <button onclick="pickG()">緑を選ぶ</button> 47 <button onclick="pickB()">青を選ぶ</button> 48 <button onclick="stroke()">書く</button> 49 <p> 50 鉛筆の色は<span id="color"></span>, 51 長さは<span id="length"></span>cm 52 </p> 53 </body> 54 55 56</html>

試したこと

console.logを挿入し、どこで想定外の演算が行なわれているか調べました。
3回目の実行で「0.009999999999999」
7回目の実行で「0.0099999999999995」
減ってしまっているようです。

補足情報(FW/ツールのバージョンなど)

書籍: ゲームで学ぶ「JavaScript入門」
著:田中賢一郎

をもとに練習しております。

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

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

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

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

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

guest

回答2

0

ベストアンサー

◆この現象が起きている理由(JavaScriptやビット演算のルール上発生しているのか?自分のコードの書き方で発生してしまっているのか?)

数値は内部で2進数で扱われているのはご存じだと思いますが、10進表現の0.01は2進表現では無限小数になります。2進数無限桁であれば表現できますが、コンピューターで扱うのは2進数有限桁なので(JavaScriptの数値だと64bitのデータ。有効桁数は53bit)、無限桁の有限桁への丸め誤差が発生して、計算を重ねると累積します。

解決策としては、lengthに保持する際に100倍して整数化して、クラス外部とのやりとりの際に100分の1にしたり100倍したりすれば、丸め誤差発生は最小限に抑えられます。
53bitで表現できる範囲の整数なら変換での誤差は出ません。

◆この現象が起きてしまったときにどんな言葉で検索をかけて原因を調べれば良かったのか?

「浮動小数点 誤差」「小数 誤差」とかでしょうか。

投稿2021/02/14 10:31

otn

総合スコア85882

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

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

NYzyanai

2021/02/14 12:51

なるほど!とてもわかりやすかったです、ありがとうございます。 基本情報技術者試験でなぜこんなに2進数変換をさせるんだろう?と思っていたのですが、 こう言うWEBアプリケーションの演算にもたしかに関係して来るから必要なんですね。 対策まで有難うございます!個人的には0.01にこだわり無いので0.25で有限にしちゃうのも楽そうですね〜 たすかりました!
otn

2021/02/14 13:07

あー、そうですね。0.25とか0.125単位にすれば、2進数で数bitで正確に表現できるので、それでいいならそっちの方が簡単です。
guest

0

言語上の仕様とのことです。

JavaScriptの数値型完全理解 - Qiita

投稿2021/02/14 10:13

phoepsilonix

総合スコア233

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問