bcdice / bcdice-js

BCDice ported package for TypeScript and JavaScript by Opal.
BSD 3-Clause "New" or "Revised" License
22 stars 9 forks source link

Fix rounding of negative numbers #45

Closed ysakasin closed 2 years ago

ysakasin commented 2 years ago

負数の除算において、RoundとFloorの処理がRubyの挙動と異なっている問題を修正した。

Roundについて

JavaScriptとRubyで負数におけるMath.round()Floor#round の挙動が異なり、Opalではその違いを吸収していない。

Xを整数とした時に、JavaScriptでは符号に関係なく、 X+0.5 > X >= X-0.5 の範囲がXに丸められる。RubyはXの絶対値について X.abs+0.5 > X.abs >= X.abs-0.5 の範囲でXに丸める。

今回の変更で、round処理時には値が負数か確認し、絶対値を使って計算するようにした。

JavaScript

> Math.round(-0.4)
-0
> Math.round(-0.5)
-0
> Math.round(-0.6)
-1

Math.round()

Ruby

irb(main):002:0> -0.4.round
=> 0
irb(main):003:0> -0.5.round
=> -1
irb(main):004:0> -0.6.round
=> -1

Float#round

Floorについて

除算の結果を整数にするために Number#to_i が使われていたが、Number#to_iFloat#floor は負数において挙動が異なる。 #to_iは単に小数点以下を0にするが、Float#floor は自身と等しいかより小さな整数のうち最大のものを返す。Rubyでは整数の除算は、Float#floor の挙動となるため、動作が合致していなかった。

irb(main):005:0> -0.5.to_i
=> 0
irb(main):006:0> -0.5.floor
=> -1
irb(main):007:0> -1/2
=> -1

今回の変更で、四則演算の端数処理で #floor を使うようにする。