[PHP-DEV] [RFC] [discussion] Correctly name the rounding mode and make it an Enum

Hi, internals!

I would like to start an RFC discussion regarding rounding modes.
https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum

As mentioned previously by Gina on the mailing list [1], there are some issues with PHP's current rounding mode.
[1] - Incorrect terminology usage for rounding modes of round() - Externals

    • First, the value is just an int, so we need to verify that the value passed is a valid rounding mode.
    • The second problem is that the behavior of the “up” and “down” modes does not match the mathematical definition. Especially for non-native speakers, the different rounding modes might also be more easily confused, compared to a naming that uses less abstract terms.

To resolve these issues, change the naming to something appropriate and use Enums instead of int constants.

Please see the RFC for details.

Regards,

Saki

To resolve these issues, change the naming to something appropriate and use Enums instead of int constants.

Hi!
I like the idea. But I don’t know

From the RFC text:

To summarize, existing features will be changed to a union type of int|\RoundingMode, and unreleased features will only accept \RoundingMode as the rounding mode argument.

I have mixed feelings about the unreleased features using a different typing for the same parameters that already exist in the existing features. On one side, the user would be forced to use the new approach and get used to it when they start to use the unreleased features, but on the other side, the code would be strange with 2 different approaches for similar features of the same “feature set”.

I think that I would use union types for everything and plan the deprecation and further removal of the Int version for the next releases for everything.

Anyway, I’m in favor of starting the movement of changing these Ints to Enums.

Thanks for working to make PHP better!

Best regards,

Erick

Hi.

I like the idea. But I don’t know
Please ignore this.

Some copy-past leftovers.

Sorry!

Hey Saki,

I like this change. When I was implementing additional rounding modes for the next PHP version I was initially struggling with the naming and this change will be helpful.

I have only one concern about the names NegativeInfinity and PositiveInfinity. They may be too formal from the user’s perspective. As we already have functions ceil and floor it’s more intuitive for developers to understand the logic of ceiling and floor rounding.

But if voters will prefer those terms then it makes sense to change the constants implemented in PHP 8.4 (and thus not released yet) from PHP_ROUND_(CEILING|FLOOR) to PHP_ROUND_(POSITIVE_INFINITY|NEGATIVE_INFINITY) for the sake of consistency.

Kind regards,

Jorg

Thank you for the clarification Erick

···

Sent from IPhone

On Fri, May 31, 2024, at 4:41 PM, Jorg Sowa wrote:

Hey Saki,
I like this change. When I was implementing additional rounding modes
for the next PHP version I was initially struggling with the naming and
this change will be helpful.

I have only one concern about the names `NegativeInfinity` and
`PositiveInfinity`. They may be too formal from the user's perspective.
As we already have functions `ceil` and `floor` it's more intuitive for
developers to understand the logic of ceiling and floor rounding.

But if voters will prefer those terms then it makes sense to change the
constants implemented in PHP 8.4 (and thus not released yet) from
`PHP_ROUND_(CEILING|FLOOR)` to
`PHP_ROUND_(POSITIVE_INFINITY|NEGATIVE_INFINITY)` for the sake of
consistency.

Kind regards,
Jorg

I was confused by those as well. It's not obvious to me what those even do. Do they mean "away from 0"? If not, then I have no clue what they are. :slight_smile:

--Larry Garfield

On Friday, 31 May 2024 at 18:15, Larry Garfield <larry@garfieldtech.com> wrote:

On Fri, May 31, 2024, at 4:41 PM, Jorg Sowa wrote:

> Hey Saki,
> I like this change. When I was implementing additional rounding modes
> for the next PHP version I was initially struggling with the naming and
> this change will be helpful.
>
> I have only one concern about the names `NegativeInfinity` and
> `PositiveInfinity`. They may be too formal from the user's perspective.
> As we already have functions `ceil` and `floor` it's more intuitive for
> developers to understand the logic of ceiling and floor rounding.
>
> But if voters will prefer those terms then it makes sense to change the
> constants implemented in PHP 8.4 (and thus not released yet) from
> `PHP_ROUND_(CEILING|FLOOR)` to
> `PHP_ROUND_(POSITIVE_INFINITY|NEGATIVE_INFINITY)` for the sake of
> consistency.
>
> Kind regards,
> Jorg

I was confused by those as well. It's not obvious to me what those even do. Do they mean "away from 0"? If not, then I have no clue what they are. :slight_smile:

--Larry Garfield

Considering that there are already "Away from 0" and "Towards 0" enum cases, the Towards Positive Infinity/Towards Negative Infinity cases "obviously" don't mean this.

Towards positive infinity means that for positive numbers you round to the integer part plus 1, and for negative numbers you "just" take the negative integer part.
Similarly, for rounding towards negative infinity positive numbers round to "just" the integer part of it, and negative numbers round to the negative integer part minus 1.

It should also be noted that ceil/floor is very English specific terminology that may not be immediately obvious to non-English speakers, thus my preference for using some variation of towards positive/negative infinity.

Best regards,

Gina P. Banyard

On Friday, 31 May 2024 at 15:49, Saki Takamachi <saki@sakiot.com> wrote:

Hi, internals!

I would like to start an RFC discussion regarding rounding modes.
PHP: rfc:correctly_name_the_rounding_mode_and_make_it_an_enum

As mentioned previously by Gina on the mailing list [1], there are some issues with PHP's current rounding mode.
[1] - Incorrect terminology usage for rounding modes of round() - Externals

• First, the value is just an int, so we need to verify that the value passed is a valid rounding mode.
• The second problem is that the behavior of the “up” and “down” modes does not match the mathematical definition. Especially for non-native speakers, the different rounding modes might also be more easily confused, compared to a naming that uses less abstract terms.

To resolve these issues, change the naming to something appropriate and use Enums instead of int constants.

Please see the RFC for details.

Regards,

Saki

IMHO, part of the RFC should be to amend the "Add 4 new rounding modes to round() function" RFC [1] by *removing* the newly introduced constant and instead exposing the functionality *only* via the new Enum.
Especially as those constant have not yet been in a stable release of PHP.

Other than that, and seeing the confusing of some other people, maybe using the names "TowardsPositiveInfinity" and "TowardsNegativeInfinity" is better.

Best regards,

Gina P. Banyard

It should also be noted that ceil/floor is very English specific terminology that may not be immediately obvious to non-English speakers, thus my preference for using some variation of towards positive/negative infinity.

This statement is subjective in my opinion. For me, it’s the contrary, that’s why I’m opposing introducing new terms to the PHP replacing ones that already exist (ceil()/floor()). I don’t have the data on such modes in other programming languages, but I checked the data in Google Trends:
https://trends.google.com/trends/explore?q=round%20toward%20positive%20infinity,ceiling%20math,round%20positive%20infinity,towards%20positive%20infinity&hl=en

Far more people search for ceiling than round toward positive infinity or round positive infinity. Of course, I may be wrong by choosing incorrect search phrases, but it’s also good to see some data/examples that changing this in PHP is for the better.

by removing the newly introduced constant and instead exposing the functionality only via the new Enum.

It brings inconsistency that some modes are accessible by ints and enums and others only by enums. If there is no deprecation plan yet I am not sure this is the right approach.

Kind regards,

Jorg

On Sat, 1 Jun 2024, Gina P. Banyard wrote:

On Friday, 31 May 2024 at 18:15, Larry Garfield <larry@garfieldtech.com> wrote:

> On Fri, May 31, 2024, at 4:41 PM, Jorg Sowa wrote:
>
> > Hey Saki, I like this change. When I was implementing additional
> > rounding modes for the next PHP version I was initially struggling
> > with the naming and this change will be helpful.
> >
> > I have only one concern about the names `NegativeInfinity` and
> > `PositiveInfinity`. They may be too formal from the user's
> > perspective. As we already have functions `ceil` and `floor` it's
> > more intuitive for developers to understand the logic of ceiling
> > and floor rounding.
> >
> > But if voters will prefer those terms then it makes sense to
> > change the constants implemented in PHP 8.4 (and thus not released
> > yet) from `PHP_ROUND_(CEILING|FLOOR)` to
> > `PHP_ROUND_(POSITIVE_INFINITY|NEGATIVE_INFINITY)` for the sake of
> > consistency.
>
> I was confused by those as well. It's not obvious to me what those
> even do. Do they mean "away from 0"? If not, then I have no clue
> what they are. :slight_smile:

Considering that there are already "Away from 0" and "Towards 0" enum
cases, the Towards Positive Infinity/Towards Negative Infinity cases
"obviously" don't mean this.

Towards positive infinity means that for positive numbers you round to
the integer part plus 1, and for negative numbers you "just" take the
negative integer part. Similarly, for rounding towards negative
infinity positive numbers round to "just" the integer part of it, and
negative numbers round to the negative integer part minus 1.

It should also be noted that ceil/floor is very English specific
terminology that may not be immediately obvious to non-English
speakers, thus my preference for using some variation of towards
positive/negative infinity.

But they're well established in existing PHP features.

cheers,
Derick

--
https://derickrethans.nl | https://xdebug.org | https://dram.io

Author of Xdebug. Like it? Consider supporting me: Xdebug: Support

mastodon: @derickr@phpc.social @xdebug@phpc.social

On Fri, 31 May 2024, Saki Takamachi wrote:

I would like to start an RFC discussion regarding rounding modes.
PHP: rfc:correctly_name_the_rounding_mode_and_make_it_an_enum

I think it would be really helpful to have a description (and examples)
for each of the rounding modes in the Enum
(PHP: rfc:correctly_name_the_rounding_mode_and_make_it_an_enum)
— that'd also be great for creating documentation later on.

cheers,
Derick

On Sun, Jun 2, 2024 at 2:27 PM Jorg Sowa <jorg.sowa@gmail.com> wrote:

It should also be noted that ceil/floor is very English specific terminology that may not be immediately obvious to non-English speakers, thus my preference for using some variation of towards positive/negative infinity.

This statement is subjective in my opinion. For me, it’s the contrary, that’s why I’m opposing introducing new terms to the PHP replacing ones that already exist (ceil()/floor()). I don’t have the data on such modes in other programming languages, but I checked the data in Google Trends:
https://trends.google.com/trends/explore?q=round%20toward%20positive%20infinity,ceiling%20math,round%20positive%20infinity,towards%20positive%20infinity&hl=en

Far more people search for ceiling than round toward positive infinity or round positive infinity. Of course, I may be wrong by choosing incorrect search phrases, but it’s also good to see some data/examples that changing this in PHP is for the better.

Well, probably plenty of people searching for “ceiling” who are remodeling their house so that statistic is probably completely useless.


In terms of rounding, towards negative/positive infinity and “up” or “down” are almost always synonyms. There IS a difference (in general) between the terms “round towards positive infinity” and “ceil” however. They are rounding in the same direction, however “ceil” usually means “round towards positive infinity regardless of the value” and “round towards positive infinity” usually means “round towards positive infinity when it is unclear which direction is closer”.

For instance (typical behavior meaning):

Ceil: 2.1 → 3
Positive Infinity: 2.1 → 2
Ceil: 2.5 → 3
Positive Infinity: 2.5 → 3
Ceil: -2.1 → -2
Positive Infinity: -2.1 → -2
Ceil: -2.5 → -2
Positive Infinity: -2.5 → -2
Ceil: -2.8 → -2
Positive Infinity: -2.8 → -3

If the behavior of that mode is to ALWAYS round regardless of the value of the remainder, then it should remain ceil IMO. It’s a pretty well understood behavior in many programming languages. However, “HALF_TOWARDS_POSITIVE_INFINITY” is a different behavior, and should not be called ceil.

The bigger issue is that “HALF_UP” and “HALF_DOWN” are utterly and completely incorrectly named. Those absolutely should be changed to something sensible, and is FAR more important IMO than this discussion about ceil.

Jordan

Hi

On 6/2/24 23:26, Jorg Sowa wrote:

Far more people search for `ceiling` than `round toward positive infinity`
or `round positive infinity`. Of course, I may be wrong by choosing

Could it be the case that folks do not need to search as much for “towards positive infinity”, because in contrast to “ceiling” there is no room for misunderstanding about what that would mean?

My native language (German) has no equivalent of “Ceiling” and “Floor”. We only have “aufrunden” (rounding up) and “abrunden” (rounding down), which we have determined to be too easy to misunderstand with regard to how they interact with negative numbers. I find “Ceiling” and “Floor” equally unclear and would likely need to look up their behavior when facing negative numbers in the documentation.

Best regards
Tim Düsterhus

Hi

On 6/3/24 19:02, Jordan LeDoux wrote:

If the behavior of that mode is to ALWAYS round regardless of the value of
the remainder, then it should remain ceil IMO. It's a pretty well
understood behavior in many programming languages. However,
"HALF_TOWARDS_POSITIVE_INFINITY" is a different behavior, and should not be
called ceil.

There's already `HalfAwayFromZero` + `AwayFromZero` as companion modes. It would make sense to me to also make it `PositiveInfinity` + `HalfPositiveInfinity` [1] instead of `Ceil` + `HalfPositiveInfinity`, which are appear to be unrelated based on their naming.

That would make it clear that those two are closely related and also that all the modes starting with 'Half' would be the ones that are only relevant if the last digit is 5, whereas the others act unconditionally.

Best regards
Tim Düsterhus

[1] Possibly with an 'Towards' inserted before the Negative/Positive.

Hi

On 6/3/24 18:21, Derick Rethans wrote:

But they're well established in existing PHP features.

That does not mean that we shouldn't attempt to do better for newly introduced APIs. Over time there will be more developers that will newly learn PHP than there are developers that already know PHP’s standard library in detail.

Of course that does not mean that we should break consistency with existing functionality without good justification, but in the case of the `RoundingMode` enum, the enum is self-contained and with the addition of the new rounding modes in PHP 8.4 [1], the existing `ceil()` and `floor()` functions are redundant with the capabilities of `round()`. Anyone who newly learns PHP would get all the functionality by just using `round()` together with one of the self-explanatory rounding modes provided by the proposed `RoundingMode` enum.

Best regards
Tim Düsterhus

[1] PHP: rfc:new_rounding_modes_to_round_function

On Sunday, 2 June 2024 at 22:26, Jorg Sowa <jorg.sowa@gmail.com> wrote:

by *removing* the newly introduced constant and instead exposing the functionality *only* via the new Enum.

It brings inconsistency that some modes are accessible by ints and enums and others only by enums. If there is no deprecation plan yet I am not sure this is the right approach.

We cannot formally deprecate the constants in the same version as introducing the enums as there would be no transition period.
We can however soft deprecate the usage of the constants in the documentation by recommending to use the enumeration instead.

However, I don't see _any_ point in having both constants and enum cases for the new modes as there is no incentive what so ever to use the enum.
It is *by design* to have an inconsistency, you want the new feature, use the new and better way.

Let's imagine we do introduce those new constants alongside the enum, from a user PoV there is no clear reason why one should use constants above enums or enums above constants, except if you care about type safety.
Now, let's fast forward in this imaginary world and we decide to formally deprecate the constants and tell people to use the enum.
For every single user that decided to use the constants, especially for the new rounding modes, they now need to go and fix their code because we didn't clearly incentivise people to use, what I deem, to be the recommended way forward.

Moreover, this equivalence will be an argument _against_ deprecating the constants.
And finally, if we decide to add actual support for half up/down rounding, there is no way to establish an equivalence with a sanely named constant because the name is already taken for an incorrect mode.

So once again, if this RFC does not remove the constants for the new rounding mode I see less of a point, because it is "just" improving the naming (which is really needs considering how bonkers wrong it currently is).
This RFC *must* be passed for 8.4 to ammend your RFC, because I frankly don't want to be doing clean-up on yet another bad decision the project did that will haunt us for decades if the current state gets released.

Best regards,
Gina P. Banyard

Hi

On 6/3/24 18:23, Derick Rethans wrote:

I would like to start an RFC discussion regarding rounding modes.
PHP: rfc:correctly_name_the_rounding_mode_and_make_it_an_enum

I think it would be really helpful to have a description (and examples)
for each of the rounding modes in the Enum
(PHP: rfc:correctly_name_the_rounding_mode_and_make_it_an_enum)
— that'd also be great for creating documentation later on.

The `RoundingMode` enum will not provide any new rounding modes, thus the existing documentation of rounding modes applies. The corresponding constant names have been mentioned.

Nevertheless I've just added a PHPDoc with a brief definition and examples to each of the enum cases.

Please note: The definition is a little simplified to make it easier to understand the differences on a conceptual level.

It assumes arbitrary precision (which floats do not provide) and it assumes that rounding always rounds to integer values. In reality the round() function supports a specified number of decimal digits, with integer rounding being rounding to 0 decimal digits. An integer rounding function can emulate rounding to a specific number of decimal digits by multiplying the input value by 10**$digits, performing integer rounding, and then dividing by 10**$digits (assuming arbitrary precision).

There's also a helpful table on Wikipedia: Rounding - Wikipedia

Hope this helps.

Best regards
Tim Düsterhus

Hi,

To summarize the discussion so far, it seems that there is a lot of support for the concept of this RFC itself.

The current points of discussion are the following two points:

  1. Whether or not to provide the new rounding modes added in 8.4 as constants.
  2. Naming of modes equivalent to floor/ceiling

Regarding 1, personally, I support Gina’s opinion of only providing the new rounding modes as an Enum.
This can be interpreted as changing the rounding mode to Enum, with the existing constants being kept simply for backward compatibility.

Regarding 2, I like the PositiveInfinity/NegativeInfinity expression. As far as I know, there doesn’t seem to be a clear distinction between these and ceil/floor.
There are several other expressions, such as upward and plus inf, but they all seem to refer to the same concept.

Regards,

Saki

···

by removing the newly introduced constant and instead exposing the functionality only via the new Enum.

It brings inconsistency that some modes are accessible by ints and enums and others only by enums. If there is no deprecation plan yet I am not sure this is the right approach.

We cannot formally deprecate the constants in the same version as introducing the enums as there would be no transition period.
We can however soft deprecate the usage of the constants in the documentation by recommending to use the enumeration instead.

However, I don’t see any point in having both constants and enum cases for the new modes as there is no incentive what so ever to use the enum.
It is by design to have an inconsistency, you want the new feature, use the new and better way.

Let’s imagine we do introduce those new constants alongside the enum, from a user PoV there is no clear reason why one should use constants above enums or enums above constants, except if you care about type safety.
Now, let’s fast forward in this imaginary world and we decide to formally deprecate the constants and tell people to use the enum.
For every single user that decided to use the constants, especially for the new rounding modes, they now need to go and fix their code because we didn’t clearly incentivise people to use, what I deem, to be the recommended way forward.

Moreover, this equivalence will be an argument against deprecating the constants.
And finally, if we decide to add actual support for half up/down rounding, there is no way to establish an equivalence with a sanely named constant because the name is already taken for an incorrect mode.

So once again, if this RFC does not remove the constants for the new rounding mode I see less of a point, because it is “just” improving the naming (which is really needs considering how bonkers wrong it currently is).
This RFC must be passed for 8.4 to ammend your RFC, because I frankly don’t want to be doing clean-up on yet another bad decision the project did that will haunt us for decades if the current state gets released.

Best regards,

Gina P. Banyard

Hi

Am 2024-06-08 02:29, schrieb Saki Takamachi:

Regarding 1, personally, I support Gina's opinion of only providing
the new rounding modes as an Enum.
This can be interpreted as changing the rounding mode to Enum, with
the existing constants being kept simply for backward compatibility.

I've talked about this with Saki in private. We both agree that providing the 4 new rounding modes only by means of the proposed `RoundingMode` enum is the right choice. I have made the necessary adjustments to the RFC text. There is a new "Rounding Modes introduced in PHP 8.4" section that explains that the 4 constants will be removed as part of the `RoundingMode` enum RFC.

Best regards
Tim Düsterhus

On Tuesday, 11 June 2024 at 20:47, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2024-06-08 02:29, schrieb Saki Takamachi:

> Regarding 1, personally, I support Gina's opinion of only providing
> the new rounding modes as an Enum.
> This can be interpreted as changing the rounding mode to Enum, with
> the existing constants being kept simply for backward compatibility.

I've talked about this with Saki in private. We both agree that
providing the 4 new rounding modes only by means of the proposed
`RoundingMode` enum is the right choice. I have made the necessary
adjustments to the RFC text. There is a new "Rounding Modes introduced
in PHP 8.4" section that explains that the 4 constants will be removed
as part of the `RoundingMode` enum RFC.

Best regards
Tim Düsterhus

Thank you, I think other than possibly prefixing the NegativeInfinity
and PositiveInfinity cases with "Towards" I am happy with the content
of the RFC.

Best regards,

Gina P. Banyard