php float 取整,PHP中浮点数计算比较及取整不准确的解决方法

本文讨论了浮点数在PHP中的计算不精确性,指出由于二进制表示的限制,简单浮点数相加可能不等于预期结果。举例展示了0.2+0.7不等于0.9的情况,并通过打印双精度格式浮点数揭示了精度损失。建议在比较浮点数时考虑精度范围,推荐使用bcadd()函数进行高精度计算。同时,针对浮点数取整问题,提出使用round()函数解决因浮点数计算导致的不准确结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浮点数计算结果比较一则浮点数计算例子如下:

$a = 0.2+0.7;

$b = 0.9;

var_dump($a == $b);

打印出的结果是:bool(false)。也就是说在这里 0.2+0.7 的计算结果与 0.9 并不相等,这显然是有违我们的常识的。

对此问题,PHP官方手册曾又说明:显然简单的十进制分数如 0.2 不能在不丢失一点点精度的情况下转换为内部二进制的格式。这和一个事实有关,那就是不可能精确的用有限位数表达某些十进制分数。例如,十进制的 1/3 变成了 0.3333333...。

我们将上面的变量用双精度格式打印出来:

$a = 0.2+0.7;

$b = 0.9;

printf("%0.20f", $a);

echo '
';

printf("%0.20f", $b);

输出结果如下:

0.89999999999999991118

0.90000000000000002220

显然在这里,实际上作为浮点型数据,其精度已经损失了一部分,达不到完全精确。所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。需要说明的是,这不是PHP的问题,而是计算机内部处理浮点数的问题!在 C、JAVA 等语言中也会遇到同样的问题。

所以要比较两个浮点数,需要将其控制在我们需要的精度范围内再行比较,因此使用 bcadd() 函数来对浮点数想加并进行精度转换(为字符串):

var_dump(bcadd(0.2,0.7,1) == 0.9); // 输出:bool(true)

浮点数取整

在《PHP 取整函数 ceil 与 floor》一文中,曾有例子:

echo ceil(2.1/0.7);    // 输出:4

?>

经过上面对浮点数计算的探讨,知道这是浮点数计算结果不完全精确造成的:

printf("%0.20f", (2.1/0.7));    // 输出:3.00000000000000044409

?>

经过上面对浮点数计算的探讨,知道这是浮点数计算结果不完全精确造成的,因此使用 round() 函数处理一下即可:

echo ceil( round((2.1/0.7),1) );

?>

虽然 round() 函数是按照指定的精度进行四舍五入,但保留小数点后一位,对我们的取整结果是没影响的。

PHP 中,将一个数值换为整数类型可以通过多种方式实现,具体取决于输入类型和期望的换结果。以下是几种常见的方法: ### 使用类型换 `(int)` 或 `(integer)` 这是最直接的方法,适用于将浮点数字符串、布尔值等换为整数类型: ```php $floatValue = 123.999; $intValue = (int)$floatValue; // 结果为 123 ``` 浮点数换为整数时会截断小数部分,而是进行四舍五入[^2]。对于字符串PHP 会尝试解析出前导的整数部分,忽略掉非数字字符: ```php $stringValue = "123abc"; $intValue = (int)$stringValue; // 结果为 123 ``` ### 使用 `intval()` 函数 `intval()` 函数允许指定进制,适用于同进制表示的字符串换为整数: ```php $hexString = "FF"; $intValue = intval($hexString, 16); // 结果为 255 ``` 该函数在处理字符串时的行为与 `(int)` 类似,但提供了更灵活的进制支持[^4]。 ### 使用 `filter_var()` 函数 `filter_var()` 可以用于验证并换为整数类型,适用于数据过滤和安全验证: ```php $input = "123"; $intValue = filter_var($input, FILTER_VALIDATE_INT); ``` 如果输入是合法的整数格式,该函数会返回 `false`,因此适用于需要验证输入有效性的场景。 ### 强制换中的注意事项 当浮点数超过整数范围时,换结果可能准确PHP 使用的整数大小依赖于平台,通常在 64 位系统上为 8 字节(即 `PHP_INT_SIZE == 8`),最大值为 `PHP_INT_MAX`(通常是 9223372036854775807)[^2]。若浮点数超出此范围,换为整数可能导致溢出: ```php $largeFloat = 9.223372e18; $intValue = (int)$largeFloat; // 可能无法正确表示为整数 ``` 对于字符串,若字符串中包含非数字字符,换将仅保留前导数字部分[^4]: ```php $invalidString = "123abc456"; $intValue = (int)$invalidString; // 结果为 123 ``` ### 示例代码:综合使用同类型换 ```php $floatValue = 123.999; $intValue1 = (int)$floatValue; // 123 $intValue2 = intval($floatValue); // 123 $stringValue = "456xyz"; $intValue3 = (int)$stringValue; // 456 $intValue4 = intval($stringValue, 10); // 456 $validInt = filter_var("789", FILTER_VALIDATE_INT); // 789 $invalidInt = filter_var("abc", FILTER_VALIDATE_INT); // false ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值