ただ、あらかじめ演算結果が有限の桁数以下であることが確実ならば、
toFixed 関数 http://www.microsoft.com/japan/developer/scripting/jscript/doc/jsmthtoFixed.htm
のように、桁数を指定して丸めてしまうことで回避できます。
今回は、これを一歩推し進めて、桁数を自動判断して丸めるようにして、利用者に桁数を意識させないような仕組みを作ってみました。
と言っても、演算結果の情報だけから必要な桁数を判断することは理論的にできません。
しかし、演算のための入力用の引数が持つ桁数情報を入手することで、演算結果に要求される桁数が分かります。したがって、演算結果を補正する関数としてではなく、加減乗の関数という形態になっています。
ロジックについてはここではとくに説明は書きませんが、長くはないコードなので解析は用意でしょう。
使用上の注意としては、これはあくまでも入力が 10 進数を前提とした値に使うものです。10 進数の世界で誤差がなくなるように演算結果を補正しているため、逆にその補正が 2 進数の世界では誤差となっています。
なお、除算は理論的に難しいと考えていますので、実装していません。
たとえば数学的に 15 / 6 = 2.5 ピッタリになるとしても、これがピッタリであることを求めるロジックは難しそうです。これを求めるくらいならば内部処理を 10 進数で計算してしまったほうが手っ取り早いかもしれません。
ただ、除算の代わりに逆数を乗算することで回避することができることも多いです。たとえば 30 / 5 は 30 * 0.2 に置き換えることができ、これにより mul 関数を使うことができます。
実際に、このページに JavaScript のコードが埋め込んであります。
以下のフォーム中の計算ボタンを押して結果を比較してみてください。
function decimalOperator(t, a, b) {
var x = "" + a;
var p = x.indexOf(".");
var m;
if (p >= 0) {
m = x.length - (p + 1);
} else {
m = 0;
}
var y = "" + b;
var q = y.indexOf(".");
var n;
if (q >= 0) {
n = y.length - (q + 1);
} else {
n = 0;
}
var k;
var c;
if (t == "+") { // add
k = Math.max(m, n);
c = (a - 0) + (b - 0);
} else if (t == "-") { // sub
k = Math.max(m, n);
c = (a - 0) - (b - 0);
} else if (t == "*") { // mul
k = m + n;
c = (a - 0) * (b - 0);
} else {
return null;
}
var z = "" + c;
if (x.indexOf("e") >= 0 || y.indexOf("e") >= 0 || z.indexOf("e") >= 0) {
return c;
}
var r = z.indexOf(".");
var d;
if (r >= 0) {
var u = z.substring(r + 1 + k, r + 1 + k + 1);
d = z.substring(0, r + 1 + k);
if (u >= "5") {
var e = "";
var w = 1;
for (var i = d.length - 1; i >= 0; i--) {
var g = d.substring(i, i + 1);
if (g >= "0" && g <= "9") {
var h = g - 0;
h += w;
w = 0;
if (h >= 10) {
h -= 10;
w++;
}
e = ("" + h) + e;
} else if (w > 0 && (g == "+" || g == "-")) {
e = g + ("" + w) + e;
} else {
e = g + e;
}
}
d = e;
}
} else {
d = z;
}
var f = d - 0;
return f;
}
function add(a, b) {
return decimalOperator("+", a, b);
}
function sub(a, b) {
return decimalOperator("-", a, b);
}
function mul(a, b) {
return decimalOperator("*", a, b);
}
var a = 0.01; var b = 0.05; var c = add(a, b); var d = sub(a, b); var e = mul(a, b);