PHP 中的舍入

发布于 2024-09-15 02:02:59 字数 146 浏览 7 评论 0原文

$a = ((0.1 + 0.7) * 10) == (int)((0.1 + 0.7) * 10);

PHP 返回 false。

有人能给我解释一下,为什么会发生这种情况吗? 第一个返回 8,第二个返回 7。

$a = ((0.1 + 0.7) * 10) == (int)((0.1 + 0.7) * 10);

PHP returns false.

Could anybody explain me, why that happens?
First returns 8, second 7.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

第七度阳光i 2024-09-22 02:02:59

引用 PHP 浮点精度手册中的大红色警告:

通常,简单的十进制小数(例如 0.10.7)无法在不损失少量精度的情况下转换为其内部二进制对应部分。这可能会导致令人困惑的结果:例如,floor((0.1+0.7)*10) 通常会返回 7,而不是预期的 8 ,因为内部表示类似于 7.9

这是因为有些分数无法用有限位数的小数表示。例如,十进制形式的 1/3 变为 0.3

因此,永远不要相信浮点数结果到最后一位,也永远不要比较浮点数是否相等。如果需要更高的精度,任意精度数学函数gmp 函数可用。

Quoting the big fat red warning in the PHP Manual on Floating Point Precision:

It is typical that simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9.

This is due to the fact that it is impossible to express some fractions in decimal notation with a finite number of digits. For instance, 1/3 in decimal form becomes 0.3.

So never trust floating number results to the last digit, and never compare floating point numbers for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available.

分分钟 2024-09-22 02:02:59

浮点运算并不精确。您可以获得 7.999,而不是 8.0...当转换为整数时,它会被截断为 7。

echo number_format((0.1 + 0.7) * 10, 20);

结果:

7.99999999999999911182

Floating point arithmetic is not precise. Instead of 8.0 exactly you can get 7.999... which gets truncated to 7 when cast to an integer.

echo number_format((0.1 + 0.7) * 10, 20);

Result:

7.99999999999999911182
独自唱情﹋歌 2024-09-22 02:02:59

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

编辑

$a = ((0.1 + 0.7) * 10) == 8;
var_dump($a);

echo '<br />';

define('PRECISION', 1.0e-08);

$a = (abs(((0.1 + 0.7) * 10) - 8) < PRECISION);
var_dump($a);

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

EDIT

$a = ((0.1 + 0.7) * 10) == 8;
var_dump($a);

echo '<br />';

define('PRECISION', 1.0e-08);

$a = (abs(((0.1 + 0.7) * 10) - 8) < PRECISION);
var_dump($a);
錯遇了你 2024-09-22 02:02:59

马克的回答击中了要害,但我认为您不需要强制转换,而是需要圆形 PHP 函数:

http://php.net/manual/en/function.round.php

Mark's response hits the nail on the head, but I think instead of casting you want the round PHP function:

http://php.net/manual/en/function.round.php

宣告ˉ结束 2024-09-22 02:02:59

来自浮点指南(点击查看详细说明):

因为计算机内部使用
格式(二进制浮点)
不能准确地表示一个数字
就像 0.1、0.2 或 0.3根本

当代码被编译或
解释后,你的“0.1”已经是
四舍五入到最接近的数字
格式,这会导致一个小
甚至在之前的舍入误差
计算发生。

From The Flaoting-Point Guide (click for detailed explanations):

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.

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.

掐死时间 2024-09-22 02:02:59

因为对浮点数进行操作并不是 100% 准确,所以在从表达式中转换值之前可能类似于 7.9999...

Because operating on floating point numbers isn't 100% accurate, propably before casting value from expression is something like 7.9999...

書生途 2024-09-22 02:02:59

您可以这样进行比较:

$a = round(((0.1 + 0.7) * 10), 1) == (int)round(((0.1 + 0.7) * 10), 1);

You can do the comparison this way:

$a = round(((0.1 + 0.7) * 10), 1) == (int)round(((0.1 + 0.7) * 10), 1);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文