Excel VBA の RoundUp() と Javascript の Math.ceil() は負の値の切り上げ方が違う

VBA 製の計算ツールを Web アプリ化している時に、切り上げの部分で少しハマったのでメモ。

結論

  • -1.01 を切り上げたらどうなる?」に対する解は二通りある
    • 解1: -2 負の方向に切り上げる
    • 解2: -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 をする)を作って対処した。