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
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 ofPHP_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): floatand 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
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 ofPHP_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): floatand 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_functionIn 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 forMaths
and 0 forMathematics
.Regards,
Saki
Math is American English spelling, Maths/Mathematics the British English one.
As we also have color (and not the "correct" colour), going with the American spelling seems better.
But I would query whether we actually need it in a namespace.
cheers
Derick
Hi
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;
}
Indeed.
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): floatand 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.
For PHP 8.4, I'd first make it int|RoundingMode
to keep the constant
values the same (in case the constants are re-used by a userland
library). Narrowing it down to just RoundingMode and updating the
constants can happen in a later version.
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.
I don't think it should be in a namespace. The name is sufficiently
unique and clear. Without a broader concept for the namespace, we
probably should not introduce one.
Best regards
Tim Düsterhus
I don't think it should be in a namespace. The name is sufficiently
unique and clear. Without a broader concept for the namespace, we
probably should not introduce one.
+1
For this, I don't think a namespace is necessary. Though I will note that
"Mathematics" is absolutely an American English term as well as British
English, even though "Maths" is not.
This will also make it easier for me to do one of the smaller improvements
I've been pondering proposing: adding some brand new rounding modes:
- Half Alternating
- Half Random
- Stochastic
Jordan
Hi
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;
}
For PHP 8.4, I'd first make it
int|RoundingMode
to keep the constant
values the same (in case the constants are re-used by a userland
library). Narrowing it down to just RoundingMode and updating the
constants can happen in a later version.
I support this change. While I don't know who would be using the rounding mode constants for other purposes, I'm not opposed to taking a more gradual approach if that's the consensus. At least a version would allow people time to realize, oops, I should not use someone else's constants. :-)
I also don't have a strong opinion between making it global vs a Math namespace. (But as Derick notes, not Maths, for consistency.)
--Larry Garfield