13、PHP 8.4 新特性 - PHP 8.4:round() 函数中的新舍入模式

作者: 温新

图书: 【PHP 8.4 新特性】

阅读: 108

时间: 2025-01-18 12:17:16

在 PHP 8.4 中,round() 函数新增了 舍入模式 的选项,使得开发者能够在四舍五入的过程中,选择不同的舍入行为。这个新增功能为开发者提供了更多的灵活性,特别是在金融计算、精度控制等场景中,能够更精确地控制舍入的方式。

<?php

declare(strict_types=1);

echo round(3.14, precision: 0, mode: PHP_ROUND_HALF_UP) . PHP_EOL; // 3
echo round(3.14, precision: 1, mode: PHP_ROUND_HALF_UP) . PHP_EOL; // 3.1
echo round(3.15, precision: 0, mode: PHP_ROUND_HALF_UP) . PHP_EOL; // 3
echo round(3.5,  precision: 0, mode: PHP_ROUND_HALF_UP) . PHP_EOL; // 4

在 PHP 8.4 之前,round() 函数支持四种舍入方法:

  • PHP_ROUND_HALF_UP:当数值正好位于两个整数中间时,远离零的方向进行舍入。例如,1.5 舍入为 2,-1.5 舍入为 -2。常量值为 int(1)。
  • PHP_ROUND_HALF_DOWN:当数值正好位于两个整数中间时,朝向零的方向进行舍入。例如,1.5 舍入为 1,-1.5 舍入为 -1。常量值为 int(2)。
  • PHP_ROUND_HALF_EVEN:当数值正好位于两个整数中间时,向最近的偶数舍入。例如,1.5 和 2.5 都舍入为 2。常量值为 int(3)。
  • PHP_ROUND_HALF_ODD:当数值正好位于两个整数中间时,向最近的奇数舍入。例如,1.5 舍入为 1,2.5 舍入为 3。常量值为 int(4)。

在 PHP 8.4 中,round() 函数新增了以下四种舍入方法:

  • PHP_ROUND_CEILING:将数值向上舍入到最接近且大于该数值的整数。例如,1.1 和 1.5 都舍入为 2,-1.1 和 -1.5 都舍入为 -1。当 $precision 参数为 0 时,返回值与 ceil 函数的返回值相同。常量值为 int(5)。
  • PHP_ROUND_FLOOR:将数值向下舍入到最接近且小于该数值的整数。例如,1.1 和 1.9 都舍入为 1,-1.9 和 -1.1 都舍入为 -2。返回值与 floor 函数的返回值相同。常量值为 int(6)。
  • PHP_ROUND_TOWARD_ZERO:将数值朝向零的方向舍入。例如,1.9 和 1.1 都舍入为 1,-1.9 和 -1.1 都舍入为 -1。常量值为 int(7)。
  • PHP_ROUND_AWAY_FROM_ZERO:将数值远离零的方向舍入。例如,1.1 和 1.9 都舍入为 2,-1.1 和 -1.9 都舍入为 -2。常量值为 int(8)。

以下表格总结了不同舍入模式下示例数值的返回值:

数值 PHP_ROUND_HALF_UP PHP_ROUND_HALF_DOWN PHP_ROUND_HALF_EVEN PHP_ROUND_HALF_ODD PHP_ROUND_CEILING PHP_ROUND_FLOOR PHP_ROUND_TOWARD_ZERO PHP_ROUND_AWAY_FROM_ZERO
0.8 1 1 1 1 1 0 0 1
1.1 1 1 1 1 2 1 1 2
1.5 2 1 2 1 2 1 1 2
1.9 2 2 2 2 2 1 1 2
-0.8 -1 -1 -1 -1 -0 -1 -0 -1
-1.1 -1 -1 -1 -1 -1 -2 -1 -2
-1.5 -2 -1 -2 -1 -1 -2 -1 -2
-1.9 -2 -2 -2 -2 -1 -2 -1 -2

这个表格展示了在不同的舍入模式下,给定数值是如何被舍入的。例如:

  • PHP_ROUND_HALF_UP:当数值正好位于两个整数中间时,远离零的方向进行舍入。
  • PHP_ROUND_HALF_DOWN:当数值正好位于两个整数中间时,朝向零的方向进行舍入。
  • PHP_ROUND_HALF_EVEN:当数值正好位于两个整数中间时,向最近的偶数舍入。
  • PHP_ROUND_HALF_ODD:当数值正好位于两个整数中间时,向最近的奇数舍入。
  • PHP_ROUND_CEILING:将数值向上舍入到最接近且大于该数值的整数。
  • PHP_ROUND_FLOOR:将数值向下舍入到最接近且小于该数值的整数。
  • PHP_ROUND_TOWARD_ZERO:将数值朝向零的方向舍入。
  • PHP_ROUND_AWAY_FROM_ZERO:将数值远离零的方向舍入。

使用 Intl 扩展 NumberFormatter 进行舍入

Intl 扩展中的 NumberFormatter 类也提供了舍入功能,并且额外支持数字的本地化。

NumberFormatter 类同样支持与 round() 函数相同的舍入模式,这些模式可以通过设置对象的属性(NumberFormatter::ROUNDING_MODE)来配置。精度则通过 NumberFormatter::FRACTION_DIGITS 属性来设置:

$formatter = new \NumberFormatter("zh-CN", \NumberFormatter::DECIMAL);
$formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, 0);
$formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, \NumberFormatter::ROUND_HALFUP);

echo $formatter->format(1.1); // 输出 1

下表显示了每个 round() 舍入模式对应的 NumberFormatter::ROUNDING_MODE 属性值:

round 模式 NumberFormatter::ROUNDING_MODE 值
PHP_ROUND_HALF_UP NumberFormatter::ROUND_HALFUP
PHP_ROUND_HALF_DOWN NumberFormatter::ROUND_HALFDOWN
PHP_ROUND_HALF_EVEN NumberFormatter::ROUND_HALFEVEN
PHP_ROUND_HALF_ODD NumberFormatter::ROUND_HALFODD
PHP_ROUND_CEILING NumberFormatter::ROUND_CEILING
PHP_ROUND_FLOOR NumberFormatter::ROUND_FLOOR
PHP_ROUND_TOWARD_ZERO NumberFormatter::ROUND_DOWN 或 NumberFormatter::ROUND_TOWARD_ZERO
PHP_ROUND_AWAY_FROM_ZERO NumberFormatter::ROUND_UP 或 NumberFormatter::ROUND_AWAY_FROM_ZERO

NumberFormatter 新增常量

  • NumberFormatter::ROUND_TOWARD_ZERO(值为 int(2)):这是 NumberFormatter::ROUND_DOWN 的别名,以与 round() 函数的 PHP_ROUND_TOWARD_ZERO 模式保持一致。
  • NumberFormatter::ROUND_AWAY_FROM_ZERO(值为 int(3)):这是 NumberFormatter::ROUND_UP 的别名,以与 round() 函数的 PHP_ROUND_AWAY_FROM_ZERO 模式保持一致。
  • NumberFormatter::ROUND_HALFODD(值为 int(8)):用于补充 NumberFormatter::ROUND_HALFEVEN 功能,但这个常量在 PHP 8.4 之前并未声明。

向后兼容性影响

PHP_ROUND_CEILINGPHP_ROUND_FLOORPHP_ROUND_TOWARD_ZEROPHP_ROUND_AWAY_FROM_ZERO 是在 PHP 8.4 中声明的新常量。

Intl 扩展中的 NumberFormatter 类增加了 NumberFormatter::ROUND_TOWARD_ZERO 作为 NumberFormatter::ROUND_DOWN 的别名,以及 NumberFormatter::ROUND_AWAY_FROM_ZERO 作为 NumberFormatter::ROUND_UP 的别名。

此外,NumberFormatter 类还声明了一个新的 NumberFormatter::ROUND_HALFODD 常量,该常量提供了与 round() 函数使用 PHP_ROUND_HALF_ODD 模式时相同的功能。这个常量在 PHP 8.4 之前并未声明,尽管 NumberFormatter::ROUND_HALFEVEN 已经存在。

请登录后再评论