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

Hi

On 6/13/24 03:28, Gina P. Banyard wrote:

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

I've discussed this with Saki. In that case the `HalfEven` and `HalfOdd` modes would also need to be renamed to `HalfTowardsEven` and `HalfTowardsOdd`, resulting in this:

     enum RoundingMode
     {
       case HalfAwayFromZero; // PHP_ROUND_HALF_UP
       case HalfTowardsZero; // PHP_ROUND_HALF_DOWN
       case HalfTowardsEven; // PHP_ROUND_HALF_EVEN
       case HalfTowardsOdd; // PHP_ROUND_HALF_ODD
       case TowardsZero; // PHP_ROUND_TOWARD_ZERO
       case AwayFromZero; // PHP_ROUND_AWAY_FROM_ZERO
       case TowardsNegativeInfinity; // PHP_ROUND_FLOOR
       case TowardsPositiveInfinity; // PHP_ROUND_CEILING
     }

Except for the `AwayFromZero` modes, every mode contains `Towards` and especially the `HalfTowardsX` modes are too similar to easily distinguish them visually.

Thus we prefer the current state of the RFC where the different modes have plenty of hamming distance, while still being sufficiently descriptive.

Best regards
Tim Düsterhus

Hi,

Naming is hard, for sure. Here is my review. I find the names mostly reasonable, except Round::PositiveInfinity and Round::NegativeInfinity. I will discuss Round::PositiveInfinity.

First:

I've discussed this with Saki. In that case the `HalfEven` and `HalfOdd` modes would also need to be renamed to `HalfTowardsEven` and `HalfTowardsOdd`

For me, the implied preposition in `HalfEven` is “to”, not “towards”. In other words, in the HalfEven mode, a half-number is replaced with the nearest even integer; it is not replaced with a integer *in the direction of* (or: *towards*) an even integer. So, `Round::HalfEven` is fine; but `Round::PositiveInfinity` does not make much sense to me, as the number is not rounded to +∞, but towards +∞.

-------

Second, “TowardsPositiveInfinity” is just a mouthful synonym for “Up”. You could just name it:

Round::Up

At this point, you may invoke either Hamming or Levenshtein and compare it negatively with `Round::HalfUp`. Yes there is a risk a confusion (and I do think that such a name is suboptimal for this reason), but the confusion is not just caused by the short Levenshtein distance. That brings to the most important part of my review.

-------

In my opinion, the most important criterion for a good name is:

The name must be clear for itself, not just when comparing it with other ones.

The problem with `Round::Up` (or `Round::[Towards]PositiveInfinity`), when you first encounter it, is that it is relatively easy to mistakingly assume that it is a “half-*” mode, and to erroneously interpret it as `Round::HalfUp` (or, its synonym `Round::HalfTowardsPositiveInfinity`).

But that the converse is false: it is impossible to interpret `Round::HalfUp` as if it were `Round::Up` (or `Round::TowardsPositiveInfinity`), because of the distinctive “Half” token that immediately indicate the right interpretation.

So, the best way to disambiguate `Round::Up` from `Round::HalfUp`, is not to replace “Up” with some creative synonym, but to add a distinctive token that plays the role of — and contrasts with — “Half”. I don’t know if the following suggestion makes sense for you, but it is the one I have found:

Round::FullUp

---------

That said, I think that there is an even better option. I know you will not like it, but bear with me. I sincerely think that the best name is just:

Round::Ceiling

It is short, distinctive, and standard across the computing industry.

Yes, this name is idiosyncratic to English and not used in several other (natural) languages, and if you don’t know English, you will not grasp the metaphor and have to just learn it. However, whatever other name you invent, you *have* to learn “ceil” anyway, because you *will* encounter it sooner or later. Many common (programming) languages, including JavaScript, C++, Java, Python, have a `ceil` function. Even if you manage not to learn any of those and to code in PHP only, you are at risk to stumble on its built-in `ceil(...)` function, or its newly-introduced `bcceil(...)` variant.

Therefore, unless we find a name that is *really* good, I suggest to not fall into the NIH syndrome, and not to force users to learn another name *in addition to* “ceiling”.

---------

For the same reason, `Round::TowardsZero` (suboptimal, because confusable with `Round::HalfTowardsZero`) could be replaced with: `Round::Truncate`.

—Claude

On Wednesday, 19 June 2024 at 20:14, Claude Pache <claude.pache@gmail.com> wrote:

Hi,

Naming is hard, for sure. Here is my review. I find the names mostly reasonable, except Round::PositiveInfinity and Round::NegativeInfinity. I will discuss Round::PositiveInfinity.

First:

> I've discussed this with Saki. In that case the `HalfEven` and `HalfOdd` modes would also need to be renamed to `HalfTowardsEven` and `HalfTowardsOdd`

For me, the implied preposition in `HalfEven` is “to”, not “towards”. In other words, in the HalfEven mode, a half-number is replaced with the nearest even integer; it is not replaced with a integer in the direction of (or: towards) an even integer. So, `Round::HalfEven` is fine; but `Round::PositiveInfinity` does not make much sense to me, as the number is not rounded to +∞, but towards +∞.

I agree with this part.

-------

Second, “TowardsPositiveInfinity” is just a mouthful synonym for “Up”. You could just name it:

Round::Up

At this point, you may invoke either Hamming or Levenshtein and compare it negatively with `Round::HalfUp`. Yes there is a risk a confusion (and I do think that such a name is suboptimal for this reason), but the confusion is not just caused by the short Levenshtein distance. That brings to the most important part of my review.

I disagree there, the main motivation of the RFC is to fix the naming of PHP_ROUND_HALF_UP because it does *not* match the mathematical behaviour of rounding half toward positive infinity.
And considering multiple other programming languages *also* have made that mistake I do not think that “TowardsPositiveInfinity” is a synonym for "Up".
Moreover, I'm not sure something being a mouthful is a good reason to name it something else.

-------

In my opinion, the most important criterion for a good name is:

The name must be clear for itself, not just when comparing it with other ones.

The problem with `Round::Up` (or `Round::[Towards]PositiveInfinity`), when you first encounter it, is that it is relatively easy to mistakingly assume that it is a “half-*” mode, and to erroneously interpret it as `Round::HalfUp` (or, its synonym `Round::HalfTowardsPositiveInfinity`).

But that the converse is false: it is impossible to interpret `Round::HalfUp` as if it were `Round::Up` (or `Round::TowardsPositiveInfinity`), because of the distinctive “Half” token that immediately indicate the right interpretation.

So, the best way to disambiguate `Round::Up` from `Round::HalfUp`, is not to replace “Up” with some creative synonym, but to add a distinctive token that plays the role of — and contrasts with — “Half”. I don’t know if the following suggestion makes sense for you, but it is the one I have found:

Round::FullUp

This is an interesting point of view, but what this tell me is not an issue with Up or Down on its own, but that seemingly for you and others the focus of rounding is how to break ties, not about the rounding itself.

Moreover, and this is the part where I think the naming of “TowardsPositiveInfinity” is better, is because you said yourself that:

the implied preposition in `HalfEven` is “to”, not “towards”

Which, at least to me, also implies that if you see something that includes "Towards" you stop thinking about the tie breaking behaviour and thus just think about the total/complete rounding behaviour.

---------

That said, I think that there is an even better option. I know you will not like it, but bear with me. I sincerely think that the best name is just:

Round::Ceiling

It is short, distinctive, and standard across the computing industry.

Yes, this name is idiosyncratic to English and not used in several other (natural) languages, and if you don’t know English, you will not grasp the metaphor and have to just learn it. However, whatever other name you invent, you have to learn “ceil” anyway, because you will encounter it sooner or later. Many common (programming) languages, including JavaScript, C++, Java, Python, have a `ceil` function. Even if you manage not to learn any of those and to code in PHP only, you are at risk to stumble on its built-in `ceil(...)` function, or its newly-introduced `bcceil(...)` variant.

Therefore, unless we find a name that is really good, I suggest to not fall into the NIH syndrome, and not to force users to learn another name in addition to “ceiling”.

I don't see how this falls into the NIH syndrome, because it has not been invented here.
The terminology chosen is standard in mathematics, and even more so in mathematical speech in other languages.

Best regards,

Gina P. Banyard

On Wed, Jun 19, 2024 at 12:16 PM Claude Pache <claude.pache@gmail.com> wrote:

Second, “TowardsPositiveInfinity” is just a mouthful synonym for “Up”. You could just name it:

Round::Up

At this point, you may invoke either Hamming or Levenshtein and compare it negatively with Round::HalfUp. Yes there is a risk a confusion (and I do think that such a name is suboptimal for this reason), but the confusion is not just caused by the short Levenshtein distance. That brings to the most important part of my review.

This is completely incorrect. “Up” is needlessly ambiguous. As evidence, I will quote from the CURRENT documentation for PHP:

“PHP_ROUND_HALF_UP Rounds num away from zero when it is half way there, making 1.5 into 2 and -1.5 into -2”
https://www.php.net/manual/en/function.round.php

Clearly it is not “just a synonym”, as the current PHP (incorrectly) equates “up” with “away from zero”. It’s the difference between rounding “up” in magnitude, and rounding “up” in value.

Any discussion about “Hamming distance” utterly pales in the face of the reality that developers will be confused because we have trained them for 20 years to expect something else. People wanting to tab-complete faster is not a good argument in my opinion for doing something that will actively cause bugs and confusion about semantical meaning.

“Up” and “Down” do not belong in a mathematical description of rounding where negative numbers exist, unless that term is consistent and WIDELY agreed on. However, to cause even FURTHER confusion, OTHER languages (such as the python function round_up) use “Up” to mean exactly what you are saying here: towards positive infinity.

The fact that this is not a consistent terminology across languages that support rounding, AND the fact that PHP has for decades used “Up” to mean “Away from zero” makes this a complete non-started in my eyes.

If there is ONE improvement to be made with this RFC, it is to completely remove “up” and “down” from the rounding terminology.

Jordan

Hi

On 6/24/24 22:11, Jordan LeDoux wrote:

If there is ONE improvement to be made with this RFC, it is to completely
remove "up" and "down" from the rounding terminology.

Please note that the RFC does not include the “Up” and “Down” terminology in its proposal. It only uses it to describe which of the ”legacy” rounding mode constants are equivalent to the proposed enum cases.

Best regards
Tim Düsterhus

Hi

please apologize the delay in getting back to you. I was absolutely swamped with mailing list mails, other work and I didn't want to give a reply that I did not give any thought.

On 6/19/24 21:14, Claude Pache wrote:

Second, “TowardsPositiveInfinity” is just a mouthful synonym for “Up”. You could just name it:

Round::Up

Except that it isn't and both the RFC and the two fine folks who already replied explained why.

At this point, you may invoke either Hamming or Levenshtein and compare it negatively with `Round::HalfUp`. Yes there is a risk a confusion (and I do think that such a name is suboptimal for this reason), but the confusion is not just caused by the short Levenshtein distance. That brings to the most important part of my review.

Please note that the comparison was not made against the corresponding “Half” mode, but rather that the term “Up” is needlessly ambiguous. As I've also replied to Jordan: The RFC intentionally does not use the Up terminology (except to refer to the existing constants, which unfortunately use that terminology).

In my opinion, the most important criterion for a good name is:

The name must be clear for itself, not just when comparing it with other ones.

The problem with `Round::Up` (or `Round::[Towards]PositiveInfinity`), when you first encounter it, is that it is relatively easy to mistakingly assume that it is a “half-*” mode, and to erroneously interpret it as `Round::HalfUp` (or, its synonym `Round::HalfTowardsPositiveInfinity`).

That is a fair concern. We shortly discussed splitting the enum into one "MidpointRoundingMode" and one other enum for the directed rounding modes, but we felt that it did not reliably solve this problem either. At least with a single enum all the 'Half' modes would appear in autocompletion.

But that the converse is false: it is impossible to interpret `Round::HalfUp` as if it were `Round::Up` (or `Round::TowardsPositiveInfinity`), because of the distinctive “Half” token that immediately indicate the right interpretation.

Right.

So, the best way to disambiguate `Round::Up` from `Round::HalfUp`, is not to replace “Up” with some creative synonym, but to add a distinctive token that plays the role of — and contrasts with — “Half”. I don’t know if the following suggestion makes sense for you, but it is the one I have found:

Round::FullUp

You might have misunderstood my email. The concerns were not that HalfTowardsZero is too similar to TowardsZero, but rather that HalfTowardsZero is too similar to HalfTowardsEven, because they share the same 11-character prefix.

That said, I think that there is an even better option. I know you will not like it, but bear with me. I sincerely think that the best name is just:

Round::Ceiling

It is short, distinctive, and standard across the computing industry.

Yes, this name is idiosyncratic to English and not used in several other (natural) languages, and if you don’t know English, you will not grasp the metaphor and have to just learn it. However, whatever other name you invent, you *have* to learn “ceil” anyway, because you *will* encounter it sooner or later. Many common (programming) languages, including JavaScript, C++, Java, Python, have a `ceil` function. Even if you manage not to learn any of those and to code in PHP only, you are at risk to stumble on its built-in `ceil(...)` function, or its newly-introduced `bcceil(...)` variant.

Therefore, unless we find a name that is *really* good, I suggest to not fall into the NIH syndrome, and not to force users to learn another name *in addition to* “ceiling”.

There is precedent for an "infinity-based" naming in other programming languages. The most mainstream one is probably C#:

But there is also MATLAB:

We can even find precedent in PHP itself. The GMP extension already has rounding mode constants GMP_ROUND_PLUSINF and GMP_ROUND_MINUSINF:

https://www.php.net/manual/en/gmp.constants.php

And to add some anecdata: Just a few days ago I fixed a bug where the floor() function was incorrectly used where rounding towards zero was desired, resulting in incorrect results for negative numbers.

The Ceiling / Floor / Up / Down naming is needlessly ambiguous, especially for non-native speakers.

For the same reason, `Round::TowardsZero` (suboptimal, because confusable with `Round::HalfTowardsZero`) could be replaced with: `Round::Truncate`.

While I think that Truncate is reasonably clear, breaking the mapping between the midpoint modes and the directed rounding modes just for this case does not appear useful.

Best regards
Tim Düsterhus

Hi

On 5/31/24 16:49, 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

We already wanted to announce the RFC vote, but then I forgot to do so and then Claude's email came in. Oh well.

Saki and I are happy with the RFC as it is and we also checked with some folks with a background in maths to see if they would make any further changes, which they answered they would not.

We plan to to open the vote on Wednesday, July 3rd.

Best regards
Tim Düsterhus