您不希望看到的东西,但是需要知道何时在php中处理浮点数
<?php
$i = (32.87*100);
echo $i; // outputs 3287
echo (int) $i; // outputs 3286 !!
echo (int) (string) $i // outputs 3287
$i
的内部表示类似于3286.9999999。
为什么$i
3287是字符串表示形式?
答案 0 :(得分:3)
让我们看一下您的代码:
$i = (32.87*100);
现在$i
的浮点数略小于3287
,如下所示:
echo sprintf('%.30f', $i) . PHP_EOL; //3286.999999999999545252649113535881
但是,当您打印(回显)它时,您将获得四舍五入的值。
echo $i; // outputs 3287
在这里我们要诀窍-将float转换为int意味着尽管点.99999999(...)
几乎等于1
(但不是!),但仅将点后的部分切除。因此输出为3286。
echo (int) $i; // outputs 3286 !!
现在,在最后一个示例中,您首先将float转换为字符串,这意味着您已经通过执行echo $i;
来完成操作,因为无论打印什么,内部都需要PHP转换为字符串。因此,将其3286.999999999999545252649113535881
强制转换为"3287"
,然后强制转换为3287
,然后打印。
echo (int) (string) $i // outputs 3287;
总而言之,将float转换为string和int的方式有所不同。
EDIT关于“取整”的进一步说明
不是真正的四舍五入。那样说我犯了一个错误。
PHP使用64位浮点数(称为 double ),以十进制表示时具有14位精度。
如PHP manual中所述:
浮点数的大小取决于平台,尽管通常值(64位IEEE格式)的最大值约为1.8e308,精度约为14个十进制数字。
这意味着,浮点数可以(在大多数情况下)包含14位数字(十进制),而点的位置无关紧要。
现在,最重要的是:
强制转换为字符串不能舍入浮点数
示例:
$a = 1.23456789012349
-最后一个9
是第15位数字,因此您将获得“四舍五入”的浮点数到1.2345678901235 $a = 12345678901234.9
-与上面相同$a = 1.99999999999999
-最后一个9
是第15位数字,因此您将获得2
作为字符串,它将完全按照浮点数进行打印,这意味着14位精度。 “舍入”是在内存中创建float变量的结构的那一刻。
最后一个例子是我们在本主题中讨论的内容。
现在,为什么我犯了这个错误并谈到“四舍五入”?
我误解了echo sprintf('%.30f', $i)
的结果。 A看到了更多的数字,并认为这是浮点数的真实值。
但不是。
我们知道,64位浮点数只有14位精度。
那么sprintf
的结果来自哪里?
答案实际上很简单。
我们已经知道,在二进制系统中并不总是能够表示十进制数。因此,例如,一个简单的0.1
浮点数(二进制表示形式)只是一个近似值,因为实际的二进制表示形式将无限长。
现在,将二进制系统转换为十进制时,它的工作原理完全相同。可以用二进制(表示每个浮点值)表示的内容,但并非总是可以用十进制表示的。
因此sprintf('%.30f', $i)
给出的是将浮点数从二进制转换为十进制的30位精度近似值。
感谢@ Quasimodo'sclone在评论中要求对此进行更精确的介绍。这使我对这个话题更加深入。
答案 1 :(得分:0)
您要将$i
(3287)转换为字符串,然后转换为int,因此结果保留为3287。
如果将$i
转换为一个整数,则将获得3286,然后如果将其转换为一个字符串,则将具有所需的内容。
尝试echo (string) (int) $i