有一道数学计算题。
$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,
我希望我能从这里得到帮助。这真的让我很沮丧。
8条答案
按热度按时间qeeaahzv1#
请尝试
sprintf
("%.2f", $c);
浮点数以基于2的幂的IEEE表示法表示,因此终止十进制数可能不是终止二进制数,这就是为什么要使用尾随数字。
正如Variable Length Coder所建议的,如果您知道所需的精度并且它不会改变(例如,当您处理货币时),则最好使用定点数,即用美分而不是美元来表示数字
这样,如果在打印前进行大量计算,就不会有任何舍入误差。
5n0oy7gb2#
使用
round()
:**注意:**您也可以选择适当的舍入模式。
**编辑:**好吧,我不明白
sprintf()
在做什么,而number_format()
没有:对比
?
brjng4g33#
只需使用bcmath库,就可以巧妙地避开所有这些问题。
只要记住阅读文档,并注意是将参数作为字符串还是数字数据类型传递。
0qx6xfy64#
您遇到了浮点数的一个陷阱;它们不能总是表示精确的小数。如果需要精确的小数值,最好使用整数,然后在最后除以所需的精度。
例如,如果您正在用表示美元(或您最喜欢的货币)的浮点数进行计算,您可能希望实际上用整数美分进行计算。
s2j5cfk05#
按预期工作(!始终使用BC函数进行真实的计算,此问题适用于所有基于C的平台):
vi4fp9gy6#
我最近在用浮点数进行计算时也遇到了这个问题。例如,我有2个浮点数,当它们相减并格式化时,值是-0.00。
我所做的是:
在我的解决方案中,我知道floatOne永远不会小于floatTwo。money_format函数只在系统具有strfmon功能时定义,而Windows没有。
50few1ms7#
如果还有人看到这一页,遇到类似的问题,浮点数减法会导致错误或奇怪的值。我想更详细地解释这个问题。罪魁祸首是浮点数。不同的操作系统和不同版本的编程语言会有不同的表现。
为了说明这个问题,我将用下面一个简单的例子来解释原因。
它与PHP没有直接关系,也不是bug。但是,每个程序员都应该意识到这个问题。
20年前,这个问题甚至夺去了许多人的生命。
1991年2月25日,一个MIM-104爱国者导弹连在计算浮点数时出现的问题,使它无法在沙特阿拉伯的达兰拦截一枚来袭的飞毛腿导弹,造成美国陆军第14军需分遣队28名士兵死亡。
但为什么会这样呢?
原因是浮点值表示有限的精度。因此,一个值在任何处理后都可能不具有相同的字符串表示形式。它还包括在脚本中写入浮点值并直接打印它,而不进行任何数学运算。
举个简单的例子:
你会期望它打印出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。
这是因为在这种情况下,你指示它应该如何阅读,以及你需要多精确。
7gcisfzg8#