JavaScriptで「小数」を扱うときは、演算誤差に注意しなければなりません。これはExtend Scriptでも同様です。

var x=20.2;
var y=20;
var z=x-y;
if (z===0.2) { alert("true"); } else { alert("false"); } //判定:false

このコードでは4行目の判定が「true」になることを期待しています。ところが実際に実行してみると「false」と判定されてしまいます。

これはJavaScriptの演算誤差により、変数Zが0.1999……という値をとるためで、JavaScriptの実行環境が採用している演算方法(IEEE 754)が、少数の演算においてわずかな誤差を許容していることに起因しています。

 

完全に解決するのは容易ではありませんが、現実的な解決策として、それぞれの値を100倍~1000倍にして演算し、結果を同じ倍数で割り戻すという方法があります。

//部分的に100倍で計算する
var x=20.2;
var y=20;
var z=(x*100-y*100)/100;
if (z===0.2) { alert("true"); } else { alert("false"); } //判定:true

性質上、整数部分での演算誤差は発生しないので、精度にあわせた倍数で演算すれば、先の「誤差による判定漏れ」は概ね解決できます。

 

なお、Extend Scriptでは以下のような方法もあります。 

//文字列化による誤差丸め処理
var x=20.2;  
var y=20;
var z=parseFloat( (x-y).toString() ); //誤差丸め処理
if (z===0.2) { alert("true"); } else { alert("false"); } //判定:true

Extend Scriptでは数値が文字列化されるときに「丸め処理」が行われます。上記の例はこの作用を利用し、「.toString()」で結果を文字列化し、それを再び「parseFloat()」で数値に戻しています。

無意味な行為ですが、結果的にこの方法で演算誤差による判定漏れを防ぐことができます。

 

< Extend Scriptでデバッグするときの注意 >

 

Extend Scriptによる「.toString()」を使った丸め処理の例を挙げましたが、この挙動はアラートダイアログやコンソール(ESTK)への書き出しでも発生します。

 

例えば上記のような演算誤差が潜んでいて、それに起因する「挙動の不自然さ」があったとします。そして以下のようにコンソールへの書き出しを割り込ませて確認しようとします。

//文字列化による丸め処理の影響をESTKで検証
var x=20.2;
var y=20;
var z=x-y;
if (z===0.2) { alert("true"); } else { alert("false"); } //判定:false
$.writeln (z); //結果:0.2!?

この場合、コンソールへ書き出される値は「0.2」になります。皮肉なことにこの「偽りの表示」が人間の予想する計算結果なので、なおさら演算誤差に気付かないまま、原因がつかめないという事態に陥ります。

これはアラートダイアログを使った場合でも、ブレークポイントを仕掛けて変数を確認しても同じことになります。

 

残念ながらこの問題に完全な対処方法はありません。なので、小数の演算が絡んでいるときは、あらかじめこの点に留意してコーディングしなければなりません。

 

 

Joomla templates by a4joomla