php浮点计算2小数点

2ic8powd  于 2022-11-28  发布在  PHP
关注(0)|答案(8)|浏览(160)

有一道数学计算题。

$a = 34.56

$b = 34.55

$a做一些计算得到这个数字
$b四舍五入到最接近的0.05以得到该数字
结果是

$c = $b - $a

应该是-0.01,但我回显了$c,显示为-0.00988888888888
我尝试使用number_format($c, 2),但输出为0.00,
如何确保$a$b正好是2位小数,后面没有隐藏的数字。
在我的php知识中,number_format只能格式化显示,但值实际上不是十进制的2,
我希望我能从这里得到帮助。这真的让我很沮丧。

qeeaahzv

qeeaahzv1#

请尝试sprintf("%.2f", $c);
浮点数以基于2的幂的IEEE表示法表示,因此终止十进制数可能不是终止二进制数,这就是为什么要使用尾随数字。
正如Variable Length Coder所建议的,如果您知道所需的精度并且它不会改变(例如,当您处理货币时),则最好使用定点数,即用美分而不是美元来表示数字

$a = 3456;

$b = 3455;

$c = $b - $a;

sprintf ("%.2f", $c/100.0);

这样,如果在打印前进行大量计算,就不会有任何舍入误差。

5n0oy7gb

5n0oy7gb2#

使用round()

$c = round($b - $a, 2);

**注意:**您也可以选择适当的舍入模式。
**编辑:**好吧,我不明白sprintf()在做什么,而number_format()没有:

$c = number_format($b - $a, 2);

对比

$c = sprintf("%.2f", $b - $a);

brjng4g3

brjng4g33#

只需使用bcmath库,就可以巧妙地避开所有这些问题。
只要记住阅读文档,并注意是将参数作为字符串还是数字数据类型传递。

0qx6xfy6

0qx6xfy64#

您遇到了浮点数的一个陷阱;它们不能总是表示精确的小数。如果需要精确的小数值,最好使用整数,然后在最后除以所需的精度。
例如,如果您正在用表示美元(或您最喜欢的货币)的浮点数进行计算,您可能希望实际上用整数美分进行计算。

s2j5cfk0

s2j5cfk05#

  • 本机计算:*
$a = 34.56;
$b = 34.55;
$c = $b - $a; // -0.010000000000005

按预期工作(!始终使用BC函数进行真实的计算,此问题适用于所有基于C的平台):

$a = '34.56';
$b = '34.55';
$c = bcsub($b, $a, 4); // -0.0100
vi4fp9gy

vi4fp9gy6#

我最近在用浮点数进行计算时也遇到了这个问题。例如,我有2个浮点数,当它们相减并格式化时,值是-0.00。

$floatOne = 267.58;
$floatTwo = 267.58;
$result = number_format($floatOne - floatTwo, 2);
print $result; //printed a string -0.00

我所做的是:

$result = abs($floatOne - $floatTwo);// Made the number positive
print money_format('%i', $result); // printed the desired precision 0.00

在我的解决方案中,我知道floatOne永远不会小于floatTwo。money_format函数只在系统具有strfmon功能时定义,而Windows没有。

50few1ms

50few1ms7#

如果还有人看到这一页,遇到类似的问题,浮点数减法会导致错误或奇怪的值。我想更详细地解释这个问题。罪魁祸首是浮点数。不同的操作系统和不同版本的编程语言会有不同的表现。
为了说明这个问题,我将用下面一个简单的例子来解释原因。
它与PHP没有直接关系,也不是bug。但是,每个程序员都应该意识到这个问题。
20年前,这个问题甚至夺去了许多人的生命。
1991年2月25日,一个MIM-104爱国者导弹连在计算浮点数时出现的问题,使它无法在沙特阿拉伯的达兰拦截一枚来袭的飞毛腿导弹,造成美国陆军第14军需分遣队28名士兵死亡。
但为什么会这样呢?
原因是浮点值表示有限的精度。因此,一个值在任何处理后都可能不具有相同的字符串表示形式。它还包括在脚本中写入浮点值并直接打印它,而不进行任何数学运算。
举个简单的例子:

$a = '36';
$b = '-35.99';
echo ($a + $b);

你会期望它打印出0.01,对吗?但是它会打印出一个非常奇怪的答案,比如0.009999999999998
像其他数字一样,浮点数double或float在内存中以0和1的字符串形式存储。浮点数与整数的不同之处在于,当我们想要查看0和1时,我们如何解释它们。它们的存储有许多标准。
浮点数通常以符号位、指数字段和有效位或尾数的形式打包成计算机数据,从左到右......
由于缺少足够的空间,十进制数不能很好地用二进制表示。因此,uou不能将1/3精确地表示为0.3333333...,为什么我们不能用二进制浮点数来表示0.01,原因是一样的。1/100就是0.00000010100011110101110000.....重复10100011110101110000。
如果0.01以二进制的01000111101011100001010的简化和系统截断形式保存,当它被转换回十进制时,其读数将类似于0.0099999....具体取决于系统(64位计算机会给予你比32位好得多的精度)。在这种情况下,操作系统决定是否打印它所看到的内容,或者如何使它以更可读的方式显示。因此,它是机器相关的,他们希望如何表示它。但它可以在语言级别上用不同的方法进行保护。
如果格式化结果,则回显number_format(0.009999999999998,2);它将打印0.01。
这是因为在这种情况下,你指示它应该如何阅读,以及你需要多精确。

7gcisfzg

7gcisfzg8#

Now you can use this 'round' function to get 2 decimal values.

$a = '34.5638';
$b = round($a,2)
34.56 // result

相关问题