一个关于数值计算的奇怪问题

2021-02-19 14:33:06 +08:00
 evil4
今天在处理一个 BUG 的时候,发现了一个很奇怪的问题,写出来让大家参观一下,可能大家也碰到过类似问题,可以讨论一下解决方法以避免后来的同学踩坑。

问题如下:
intval(157.2*100)

我们直观看的话应该觉得输出 15720,但是他实际输出是 15719

我分别输出 157.2 * 100, 结果 15720
然后 intval(15720) 结果 15720

但是为什么上面这个就会输出 15719 呢?有高手指点一下吗?
1671 次点击
所在节点    PHP
9 条回复
carity
2021-02-19 14:36:00 +08:00
浮点精度问题
fengpan567
2021-02-19 14:56:06 +08:00
转成整数进行计算
joesonw
2021-02-19 14:57:53 +08:00
eastphoton
2021-02-19 15:00:53 +08:00
日经了。十进制下的有限小数可能是二进制下的无限循环小数,存不了。

0.2D=0.00110011B 无限循环,从浮点可存储位数截断后变成 0.19xxx


不允许误差不要用浮点。
mrgeneral
2021-02-19 15:03:38 +08:00
> 以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118...。

如果确实需要更高的精度,应该使用 BC 或者 GMP 。
debuggerx
2021-02-19 15:04:02 +08:00
round()
zhengwenk
2021-02-19 16:13:00 +08:00
var_dump(157.2 * 100)
float(15720)

157.2*100 === 15720
false
Jooooooooo
2021-02-20 00:00:09 +08:00
有些十进制看起来可以表达, 其实二进制表达不了.
Rache1
2021-02-20 09:21:31 +08:00
换成 BC Math 方法。
bcmul('157.2',100,0)

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

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

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

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

© 2021 V2EX