Excel VBA の RoundUp() と Javascript の Math.ceil() は負の値の切り上げ方が違う
VBA 製の計算ツールを Web アプリ化している時に、切り上げの部分で少しハマったのでメモ。
結論
- 「
-1.01
を切り上げたらどうなる?」に対する解は二通りある- 解1:
-2
負の方向に切り上げる - 解2:
-1
正の方向に切り上げる
- 解1:
- VBA の
Application.WorksheetFunction.RoundUp(-1.01, 0)
は-2
を返す - Javascript の
Math.ceil(-1.01)
は-1
を返す
当たり前に使っている数学関数も、言語(実装)が違うと挙動が違ってくることがあるので、ちゃんと確かめてから使いましょう。
ハマったこと
(1) VBA で Application.WorksheetFunction.RoundUp(x, 0)
を部分を、「切り上げは Javascript では Math.ceil(x)
だよね」と捉えて実装した。
(2) 実装した関数やクラスは、Unittest を適宜通していたが、「負の値を切り上げる」パターンはテストしてなかった。
(3) 画面レベルのテストの時に「なんか結果が微妙に合わない」現象に遭遇。
で、デバッガで辿ってみると、切り上げの部分で -1 と -2 の違いが出てましたとさ。
で、切り上げ方向はどっちが正しいの?
Ans: わかりません
先人
同じようにハマった方がいらっしゃいました。
おわりに
Ceiling の挙動の違いについてメモしたかっただけなので、テスト方法がどうこう等はこれ以上議論しない。
それにしても切り上げ方向の絶対的な正解は無さそうだし、もう少し調べていると銀行丸めだのなんだの、と意外と罠が多い印象も受けたので、うん、どうすればいいんだろこれ。とりあえず今回は「VBA 製ツールと同じ結果を返す」が要件だったので、Javascript 側では Math.ceil() のラッパー関数(与えられた数 v が負の時は return Math.ceil(v) - 1
をする)を作って対処した。