简体   繁体   English

PHP四舍五入时精度不正确

[英]PHP incorrect precision while rounding off number

I need to round some numbers and get modifying value. 我需要舍入一些数字并获得修改价值。

I've tried: 我试过了:

$Num=12.456;
$RoundDiff=$Num-round($Num,2);
$Num=round($Num,2);
echo $Num.'<br/>'.$RoundDiff;

but I've got: 但我有:

12.46
-0.0040000000000013

while my expected result was: 而我的预期结果是:

12.46
-0.004

What's wrong? 怎么了?
How can I get what I need? 我如何获得所需的东西?

Try below code. 尝试下面的代码。 It will give you the expected result. 它会给您预期的结果。 I have just rounded off the difference. 我已将差额四舍五入。

$Num       = 12.456;
$RoundDiff = $Num-round($Num,2);
$Num       = round($Num,2);
echo $Num.'<br/>'.round($RoundDiff,3);

CodePad 键盘

There is issue in precision of floating point values. 浮点值的精度存在问题。 Refer this article for reference - The PHP floating point precision is wrong by default 请参阅本文以供参考- 默认情况下,PHP浮点精度不正确

If you want exact precision you can use bcmath or gmp . 如果需要精确的精度,可以使用bcmathgmp

Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all. 因为在内部,计算机使用的格式(二进制浮点数)根本无法准确表示一个数字,例如0.1、0.2或0.3。

When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens. 编译或解释代码时,“ 0.1”已经舍入为该格式的最接近的数字,即使在计算之前,也会产生小的舍入误差。 — floating point guide —浮点指南

Another Reference : 另一个参考:

Given that the implicit precision of a (normal) IEEE 754 double precision number is slightly less than 16 digits 3 , this is a serious overkill. 鉴于(正常)IEEE 754双精度数字的隐式精度略小于16位数字3 ,这是一个严重的过大杀伤力。 Put another way, while the mantissa is composed of 52 bits plus 1 implicit bit, 100 decimal digits can carry up to 100*log2(10) =~ 332 bits of information, around 6 times more. 换句话说,尾数由52位加1个隐含位组成,而100个十进制数字最多可以承载100 * log2(10)=〜332位信息,约为6倍。

Given this, I propose changing the default precision to 17 (while the precision is slightly less than 16, a 17th digit is necessary because the first decimal digit carries little information when it is low). 鉴于此,我建议将默认精度更改为17(虽然精度略低于16,但第17位是必需的,因为第一个十进制数字在较低时几乎没有信息)。 — source - 资源

BCMATH : As requested in comments BCMATH: 按评论要求

$a = 12.456;
$b = round($a,2);
echo 'a ='.$a.'<br>';
echo 'b ='.$b.'<br>';
echo bcsub($a, $b, 3);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM