【PHP8.4】round関数で任意桁数の切り捨て切り上げができるようになる

[round](https://www.php.net/manual/ja/function.round.php)は四捨五入する関数です。
PHP8.4以降、この関数で小数の切り捨て切り上げができるようになります。

あれ？[ceil](https://www.php.net/manual/ja/function.ceil.php)・[floor](https://www.php.net/manual/ja/function.floor.php)は？

実はceil・floorは桁数指定ができないんですよね。
必ず整数値にさせられてしまい、小数点3桁で切り捨てみたいなことができないのであまり役に立ちません。

ということで以下は該当のRFC、[Add 4 new rounding modes to round() function](https://wiki.php.net/rfc/new_rounding_modes_to_round_function)の日本語訳です。

なお、この後[Correctly name the rounding mode and make it an Enum](https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum)というRFCも受理されて定数がENUMに置き替えられたので、置き換え後の状態で記載しています。


# PHP RFC: Add 4 new rounding modes to round() function

## Introduction

このRFCでは、round関数に4種類の新しいモードを追加します。
・[RoundingMode::PositiveInfinity](https://en.wikipedia.org/wiki/Rounding#Rounding_up)
・[RoundingMode::NegativeInfinity](https://en.wikipedia.org/wiki/Rounding#Rounding_down)
・[RoundingMode::AwayFromZero](https://en.wikipedia.org/wiki/Rounding#Rounding_away_from_zero)
・[RoundingMode::TowardsZero](https://en.wikipedia.org/wiki/Rounding#Rounding_toward_zero)

[round関数のユーザノート](https://www.php.net/manual/en/function.round.php)で最も高評価の2コメントが丸めモードについての話であり、特にトップコメントは300票以上という突出した評価を受けています。

また、[NumberFormatter](https://www.php.net/manual/en/class.numberformatter.php)はここで提案するモードを既に実装しています。


## Proposal

round関数の丸めモード引数として、4つのEUNUMを追加します。

・RoundingMode::PositiveInfinity 引数より大きい最小の整数に丸める。
・RoundingMode::NegativeInfinity 引数より小さい最大の整数に丸める。
・RoundingMode::AwayFromZero ゼロから離れた方に丸める。
・RoundingMode::TowardsZero ゼロに近い方に丸める。

## Backward Incompatible Changes

下位互換性のない変更はありません。

## Proposed PHP Versions

PHP8.4。

## Questions

### Why not use functions ceil() and floor()?

どうしてceil関数やfloor関数を使わないの？

ceil関数やfloor関数は整数に丸めるので、指定された桁数で丸めることができません。

round関数に渡す桁数が0の場合に完全に等しくなります。

```php
ceil($number)  === round($number, 0, RoundingMode::PositiveInfinity); //true
floor($number) === round($number, 0, RoundingMode::NegativeInfinity);   //true
```

### Why not the names PHP_ROUND_UP and PHP_ROUND_DOWN?

どうして定数名がPHP_ROUND_UP・PHP_ROUND_DOWNでないの？

ほぼ同じ定数名が既に[NumberFormatter](https://www.php.net/manual/en/class.numberformatter.php)にあります。
これは『ゼロから離れた方に丸める』『ゼロに近い方に丸める』を意味していますが、CEILINGやFLOORと区別がわかりにくくたいへん曖昧であるため、ROUND_TOWARD_ZERO/ROUND_AWAY_FROM_ZEROとしました。

訳注：この後ENUMになりました。


### Why not the enum implementation for the rounding modes?

丸めモードにENUMを使わないのはなぜ？

このRFCは既存関数の拡張であるため、既存の実装を踏襲しています。
ENUMの導入は、このRFCには含まれません。

訳注：この後ENUMになりました。


## Proposed Voting Choices

投票期間は2023/11/15～2023/11/30、投票の2/3の賛成で受理されます。

本RFCは賛成19反対0の全会一致で可決されました。

また同時に定数ROUND_UPをROUND_AWAY_FROM_ZEROに改名しようという投票も行われたのですが、こちらは却下されました。

訳注：この後ENUMになりました。


## Implementation

https://github.com/php/php-src/pull/12056


# 感想

このRFCが受理された時点では、[round関数](https://www.php.net/manual/ja/function.round.php)の丸めモードはこれまでのPHP_ROUND_HALF_UP・PHP_ROUND_HALF_DOWN・PHP_ROUND_HALF_EVEN・PHP_ROUND_HALF_ODDの4種類に加え、さらに4種類PHP_ROUND_CEILING・PHP_ROUND_FLOOR・PHP_ROUND_AWAY_FROM_ZERO・PHP_ROUND_TOWARD_ZEROが増えることになりました。

わかりにくい！

定数がとてもつらいということは開発陣にももちろん共有されていて、別途[Correctly name the rounding mode and make it an Enum](https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum)というRFCが提出されました。
こちらも無事受理されたため、結果としてPHP8.4以降は`round($number, 0, \RoundingMode::HalfAwayFromZero);`のように書けるようになりました。
めでたし。

このふたつのRFCによって、関数[round](https://www.php.net/manual/ja/function.round.php)は機能も増え、書き方もわかりやすくなりました。

ところでceil/floorは完全にroundの下位互換になってしまいました。
ということで、もしかしたら今後は削除されるかもしれませんね。