Hi Gina, > Hello internals, > > While reviewing the PR for the "Adding bcround, bcfloor and bcceil to BCMath" > RFC [1] with the different rounding modes, > I was made aware of the unfortunate wrong terminology usage of > PHP_ROUND_HALF_UP and PHP_ROUND_HALF_DOWN. > > Indeed, PHP_ROUND_HALF_UP is implemented as "rounding half away from zero" > and not "rounding half up" (which is also called rounding toward positive > infinity). > The behaviour for positive numbers is the same, however for negative numbers > the rounding *is* different. > In the same vein, PHP_ROUND_HALD_DOWN is implemented as "rounding half toward > zero" and not "rounding half down" (/round half toward negative infinity). > > Taking -1.5 as our number: > - Rounding half-up: -1 > - Rounding half away from zero: -2 > - Rounding half-down: -2 > - Rounding half towards zero: -1 > > For a detailed explanation about rounding, the Wikipedia page is of great > use. [2] > And the following rounding calculator on Calculator Soup is useful to check > the differences and behaviour of different rounding modes. [3] > > It should be noted that PHP is in good company about being wrong about those > two rounding modes, Java, Python, and Ruby (and probably others) are also > wrong in this regard. > > Considering that PHP 8.4 is also adding new rounding modes via the "Add 4 new > rounding modes to round() function" RFC [4] attempting to solve this issue in > this next version of PHP seems like a good idea. > In my discussions with Saki about this issue, it seems that her and Tim have > thought about creating a new enum for rounding modes, looking something like > this: > > enum RoundingMode { > case HalfAwayFromZero; > case HalfTowardsZero; > case HalfEven; > case HalfOdd; > case TowardsZero; > case AwayFromZero; > case NegativeInfinity; // or case Floor; > case PositiveInfinity; // or case Ceiling; > } > > and change the signature of round from: > round(int|float $num, int $precision = 0, int $mode = PHP_ROUND_HALF_UP): > float > to > round(int|float $num, int $precision = 0, RoundingMode $mode = > RoundingMode::HalfAwayFromZero): float > > and changing the definition of the existing constants to effectively be: > define('PHP_ROUND_HALF_UP', RoundingMode::HalfAwayFromZero); > define('PHP_ROUND_HALF_DOWN', RoundingMode::HalfTowardsZero); > define('PHP_ROUND_HALF_EVEN', RoundingMode::HalfEven); > define('PHP_ROUND_HALF_ODD', RoundingMode::HalfOdd); > > This should not cause any BC breaks, while allowing us to potentially > implement the half up/down rounding modes properly, and deprecate the > existing rounding constants in the future to get rid of the confusing names. > > I wanted to know if anyone has any object to introducing this new enum and > signature change. > The only thing I could think of is if this enum should be in a new Maths (or > Math or just Mathematics to not need to deal with regional difference in the > short spelling of "Mathematics") namespace. > > Best regards, > > Gina P. Banyard > > [1] https://wiki.php.net/rfc/adding_bcround_bcfloor_bcceil_to_bcmath > [2] https://en.wikipedia.org/wiki/Rounding > [3] > https://www.calculatorsoup.com/calculators/math/rounding-methods-calculator.php > [4] https://wiki.php.net/rfc/new_rounding_modes_to_round_function
In my discussions with Tim, I want to make it clear that all ideas derived are Tim's. :) Now, of course I agree with this, and agree with using namespaces. However, if didn't use namespaces, that's fine by me. For reference, we found approximately 100 pieces of code using the namespace `Math` on Github Code Search. There are only a few cases for `Maths` and 0 for `Mathematics`. Regards, Saki