PHP 果然是世界上最好的语言,再也不相信 var_dump() 了

2015-01-21 17:06:34 +08:00
 laoyuan
<?php
$a = 57; //或者 $a = ‘57’;
$b = '0.57' * 100;
$c = round('0.57' * 100);
var_dump( $b, $c, $a == $b, $a == $c);
?>

float(57)
float(57)
bool(false)
bool(true)

谁能解释为什么加 round 就 true 了?PHP Version 5.5.20
5664 次点击
所在节点    PHP
44 条回复
bombless
2015-01-21 17:37:24 +08:00
你看,你这就属于学艺不精了……

我 C 语言一样复现给你看
#include <stdio.h>
double round(double);
int main() {
double a = 57;
double b = .57 * 100;
double c = round(.57 * 100);
printf("%f, %f, %d, %d", b, c, a == b, a == c);
return 0;
}

输出是 57.000000, 57.000000, 0, 1

你需要学习的是浮点数,不是 PHP
eslizn
2015-01-21 17:37:32 +08:00
round返回的是浮点啊,被蠢哭
laoyuan
2015-01-21 18:01:18 +08:00
@bombless
为什么加了 round 的浮点就总是和 int 相等呢,它比普通的浮点高级在哪里??
tabris17
2015-01-21 18:03:19 +08:00
你看看 $b == $c 的结果,会有惊喜
laoyuan
2015-01-21 18:04:25 +08:00
@eslizn 是啊,返回的是浮点,但进行比较的时候又表现出一副 int 的样子来
alex321
2015-01-21 18:05:52 +08:00
laoyuan
2015-01-21 18:07:26 +08:00
@tabris17 没有惊喜,至少没打脸
bombless
2015-01-21 18:12:28 +08:00
@laoyuan 不是高级不高级的……

round之后就是整数了。

浮点数就是二进制表示的小数。你打印出来的是十进制的小数。
所以接下来我就按二进制小数和十进制小数讲解了。
另外我说的都是有限小数,下面看的时候要把二进制小数理解成二进制表示的有限小数。十进制的情况也同理。


只有它是整数的时候,二进制才能和十进制表示无损地互换——就是说,可以把二进制小数换成一个十进制表示,再把转换结果换回一个二进制表示,这个表示能和最早这个二进制表示是一样的。

以上说的是一般的情况。实际上针对上面说的这种转换,已经有算法可以实现对任意浮点数做这种“无损”的转换了。但是这个转换有一些缺点:
1. 比较晚才发现了这样的算法。这个看似简单的问题对人类的大脑来说还是比较复杂,
2. 换出来的十进制表示基本上都很长,
3. 性能不太好。


因此一般显示的浮点数,虽然是有办法精确表示的,但是出于实用的目的一般选择不精确表示。
这就是为什么 c 和 b 不一样,但打印的结果是一样的。


所以如果你需要表示整数,那就要特意的取整。不知道这么说解释清楚没有。
wenjuncool
2015-01-21 18:13:22 +08:00
学艺不精了吧,浮点数本来就不精确
tabris17
2015-01-21 18:14:05 +08:00
@laoyuan 哎。烦请运行下var_export(0.57*100);查看结果

你需要补课啊 http://zh.wikipedia.org/wiki/IEEE_754
revlis7
2015-01-21 18:14:33 +08:00
66beta
2015-01-21 18:16:19 +08:00
官网手册的示例
<?php
echo round(3.4); // 3
echo round(3.5); // 4
echo round(3.6); // 4
echo round(3.6, 0); // 4
echo round(1.95583, 2); // 1.96
echo round(1241757, -3); // 1242000
echo round(5.045, 2); // 5.05
echo round(5.055, 2); // 5.06
?>
ooh
2015-01-21 18:20:43 +08:00
我想楼主你要没想明白的是这个://(int)('0.57' * 100)=56//
laoyuan
2015-01-21 18:36:22 +08:00
我大概明白这个问题了,int 和 float 进行比较时,把 int 转为 float 值再比较,而 round() 返回的 float 值恰恰是其对应的整数的浮点值,所以 round() 尽管是 float,但和 int 比较时总是相等的。
FrankFang128
2015-01-21 18:39:55 +08:00
浮点数就不要比较是否相等了
laoyuan
2015-01-21 18:43:36 +08:00
@FrankFang128 不,就用 round 比较,生产环境都是这么做的
tabris17
2015-01-21 18:43:41 +08:00
其实这个问题是:为什么 round() 返回一个 float,但和 int 比较时总是相等的,别的 float 却没有这个技能

===============

<?php
var_dump(57.0 == 57, 0.57*100 == 57.0);

怎么就别的float没这个技能了
lijinma
2015-01-21 18:51:02 +08:00
@laoyuan 楼主,你最后的这个理解是正确的,上面有几个弟兄问非所答。。真是无语。
qwlhappy
2015-01-21 18:57:00 +08:00
其实应该是var_dump的锅
laoyuan
2015-01-21 18:59:34 +08:00
@qwlhappy 我也发现了! 用 var_export 就好了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/164207

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX