そんなの誰でも知ってるよって声が聞こえてきそうですが、自分がはまったことを晒すのは人の時間の節約に繋がるはずと信じて。
【注】結論だけ見たい人は、一番下まですっ飛んでいってください。
JavaScriptで用意されている関数
まず単純な四捨五入、切り上げ、切り捨てから。
const value = 123.45
console.log("四捨五入: " + Math.round(value))
console.log("切り上げ: " + Math. ceil(value))
console.log("切り捨て: " + Math. floor(value))
四捨五入: 123
切り上げ:124
切り捨て:123
残念な所としては、少数点第一位で処理して整数になるところでしょうか。
融通が効かない子で、これ以外やってくれません。
任意の桁で行うには?
ここでは、1の位でやってみます。
const value = 123.45
console.log("四捨五入: " + Math.round(value/10)*10)
console.log("切り上げ: " + Math. ceil(value/10)*10)
console.log("切り捨て: " + Math. floor(value/10)*10)
四捨五入: 120
切り上げ: 130
切り捨て: 120
上手くいきました。少数点第1位で処理されることを逆手にとって、10で割って少数点をずらした後、結果に10を掛けることで再び元の位に戻したというものです。
関数にしておこう!
ここでは四捨五入を例にしてみます。
function round(value, base) {
return Math.round(value / base) * base
}
これで123.5を手に
console.log("四捨五入: " + round(123.456, 0.1))
四捨五入: 123.5
無事に成功!
ついでに123.46も
console.log("四捨五入: " + round(123.456, 0.01))
四捨五入: 123.46000000000001
なんか様子が違います。バグってませんか?JavaScriptさん状態。
何故なのか【飛んできた人、ここだけ読んでください】
原因は、JavaScriptの浮動小数の計算に丸め誤差があることを忘れてしまっています。
2進数を用いた近似値で計算している弊害のようです。
せっかくMath.round()で計算したあとで、0.01という少数を再び計算に参加させていますね。
試しに以下のようなテストをしてみます。
function round(value, base) {
return Math.round(value / base) * base;
}
function round2(value, base) {
return Math.round(value * base) / base;
}
console.log("四捨五入: " + round(123.456, 0.01))
console.log("四捨五入: " + round2(123.456, 100))
この処理は脳内では同じになるのですが、実際にやると
四捨五入: 123.46000000000001
四捨五入: 123.46
こうなります。
車輪の再発明をしても仕方ないので、万能な?round関数の自作は差し控えたいと思います...
まだもう一段?間違いを犯しているかも知れませんが、お気づきの点がありましたら、やさしく教えてください。