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
5667 次点击
所在节点    PHP
44 条回复
mcfog
2015-01-21 19:00:46 +08:00
简单来说

永远不要用`==`

无论是JS还是PHP

毕竟他们都是世界上最好的语言
laoyuan
2015-01-21 19:01:28 +08:00
@mcfog 严重同意LS
Delbert
2015-01-21 19:08:33 +08:00
我试了一下
$a = 5.7;
$b = 0.57 * 10;
$c = round(0.57 * 10, 1);
var_dump( $a,
$b,
$c,
$a == $b,
$a === $b,
$a == $c,
$a === $c);

结果是:
float(5.7)
float(5.7)
float(5.7)
bool(false)
bool(false)
bool(true)
bool(true)

没想明白ing...
bombless
2015-01-21 19:13:38 +08:00
@Delbert a 和 c 是整数,b 不是,就这么简单。
laoyuan
2015-01-21 19:18:09 +08:00
@Delbert
5.7 和 round(0.57 * 10, 1) 是一个数,都是5.7对应的 float 值,而0.57 * 10 这种对 float 进行运算得到的 float,就是一个不可预知的数了,总之 float 的运算很神奇
bombless
2015-01-21 19:27:02 +08:00
噗,我24楼看错了,不好意思。

如果真的需要比较浮点数,一般是确定一个可容忍的精度,然后根据这个精度比较两个浮点数的差。

如果可能的话最好就比较整数,像云风的ejoy游戏引擎为了避开这个问题就把所有的数乘以1024,这样以一定损失为代价,全部都进行整数的比较。
货币的话常常就直接用十进制表示,不用浮点数了。
jevonszmx
2015-01-21 19:37:36 +08:00
http://docs.php.net/manual/zh/language.types.float.php
php官方文档红字警告:

浮点数的精度

浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。
此外,以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118...。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。
picasso250
2015-01-21 20:02:18 +08:00
看到楼主这样的语言使用者我就明白为什么PHP是世界上最好的语言了
endrollex
2015-01-21 20:40:04 +08:00
除非你能搞清这个底层是怎么实现的,是不是bitwise comparison,否则返回什么都没错,浮点根本不能用 ==
Kilerd
2015-01-21 21:38:44 +08:00
@bombless double输出要用%lf
laoyuan
2015-01-21 22:55:56 +08:00
@picasso250
7年PHP经验不是吹的!
laoyuan
2015-01-21 22:59:35 +08:00
@endrollex 浮点根本不能用 ==
round 之后就能用了啊,虽然 round 得到的也是浮点
ioth
2015-01-22 15:12:19 +08:00
一半语言无所谓,一半比较说不同,不让比较的除外。
ryd994
2015-01-22 15:15:00 +08:00
正常写程序都是不能直接比较浮点的,要比较的话都是 abs(a-b)<某个精确度
即使是round的结果,如果是浮点数,也无法保证今后就是相等的
这在任何语言里都是,大多数编程教学里也一定会讲到这一点,你写了7年程序还不知道……
生产环境里比较round结果……呵呵……
PHP是世界上最好的语言,可见一斑
laoyuan
2015-01-22 15:22:29 +08:00
@ryd994 那要 round 还有啥用啊,那我转为字符串再比较吧
ryd994
2015-01-22 15:38:14 +08:00
@laoyuan 字符串…………
假如我的需要精确到小数点后10位
比较abs(a-b)<c只需要一次减法,一次abs,一次浮点比较
比较字符串,且不说round和转换的开销,需要整数比较10次(字符就是整数),性能根本没法比
当然,鉴于是PHP,性能就呵呵无所谓了
xwsoul
2015-01-24 23:47:59 +08:00
为何浮点的梗还在说...这样欺负PHP真的好么? T__T
laoyuan
2015-01-25 08:38:59 +08:00
@xwsoul 这次主要在说 round 啊
xwsoul
2015-01-25 22:57:10 +08:00
@laoyuan 是时候看看隐式类型转换的原则了
round 玩来玩去还是浮点啊...
57.0 == 57 有什么问题么?
需要类型判断用, 57.0 === 57
huson
2015-02-08 18:51:31 +08:00
楼主 没仔细看手册呀,float 那章有解释的

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

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

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

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

© 2021 V2EX