JavaScript 和 PHP 中的浮点数和一致性的加法

Addition with floating point numbers in JavaScript and PHP and consistancy

提问人:Brett 提问时间:8/30/2018 更新时间:8/30/2018 访问量:395

问:

我相信很多人都经历过,我在浮点数学方面遇到了一些问题 - 我在 JavaScript 中修复了这个问题,但是虽然在 PHP 中看起来还可以,但我想确保它可以被依赖,因为它与 JS 版本略有不同。

JavaScript的:

var item = 25.00;
var postage = 24.99;

((item + postage) * 100) // 4998.999999999999

明明我不想要这个,我想要,所以我改成这个:49.99

((item + postage) * 100).toFixed(0) // 4999 (string)

然后为了更好地衡量,我将其更改为:

provideFloat((book_price + shipping_cost) * 100).toFixed(0)) // 4999 (float)

function provideFloat(num) {
    return parseFloat(num.replace(/,/g, ''));
}

现在,我需要在PHP端这个数字进行测试,看看它们是否匹配,所以我尝试了这个(例如):

PHP格式:

$item = 25.00;
$postage = 24.99;

echo ((item + $postage) * 100); // 4999

因此,正如您所看到的,与 JavaScript 不同的结果 - 我是否可以依靠这是“正确的”进行比较,而不是以类似的东西结束?4998.999999999999

出于兴趣的缘故,我尝试应用与JavaScript类似的技术,使用JS在其函数中使用的类似方法,包括:toFixed

$number = (($item + $postage) * 100);
$expo = pow(10,0);
$number = intval($number * $expo) / $expo;

echo $number; // 4998

...我得到了而 JS 得到了 - 那么我应该坚持实际得到的结果吗?这可以信赖吗?499849994999

..还是你必须走这样的极端?

$res = (($item + $postage) * 100);
$res = (float) number_format($res, 0, '.','');
echo $res; // 4999

我的用例是我需要将浮点数(美元)转换为美分,然后将它们从客户端到服务器端进行比较。

javascript php 点浮 点精度

评论

1赞 MonkeyZeus 8/30/2018
我还没有通读整个问题,因为它很长,但我没有看到提到使用 bcmath 库。如果您的应用程序中需要精确的浮点运算,则应使用各种函数并确保指定精度刻度。bcmath
0赞 MonkeyZeus 8/30/2018
此外,您应该使用 math.js 进行准确的 JS 算术。我还没有验证,但我是 99.989999999999999948840923025273% (PHP 98.99+1) 肯定您的解决方案会在某个时候光荣地失败。
0赞 Brett 8/30/2018
谢谢你 - 我的意思是我确实希望它是准确的,但更多的是关于双方都准确/返回相同的结果。
0赞 Brett 8/30/2018
@MonkeyZeus哈......确切地说,为什么我要求明确我目前正在做的事情是否可以依赖。
1赞 MonkeyZeus 8/30/2018
我很遗憾地看到你忽略了这些帖子中讨论的所有其他内容。我还没有验证,但该解决方案不可靠,因为它在执行浮点运算后对数字进行四舍五入,因此您正在四舍五入并且结果不正确。您的“解决方案”围绕着结果的格式化,而不是计算的准确性。垃圾进就是垃圾出;我不在乎你在那头猪身上涂了多少口红。.toFixed()

答:

1赞 Devon Bessemer 8/30/2018 #1

简单回答:不。你不能依赖PHP或任何语言中的浮点精度。虽然它可能适用于此示例,但在某些情况下它不匹配。

如果需要精度,请使用整数进行数学运算,或者将 bcadd() 与字符串一起使用。

如果足够接近就可以了,你应该能够摆脱 round()。number_format() 不适合用于比较,只能用于格式化(参见千位分隔符)。

评论

0赞 Brett 8/30/2018
所以你的意思是对JS和PHP的结果使用round?我只需要把数字变成整分,没有小数点和你期望的结果。(item + postage) * 100
0赞 Devon Bessemer 8/30/2018
是的,虽然不精确,但对于您的用例来说,在两种语言中四舍五入到整数可能就足够了。