PHP的intval函数的运行机制,intval(0.58*100)输出 57

今天PHP的学员去面试,其中一道面试题是echo intval(0.58*100) 输出多少,为什么?

按照正常思维输出58 ,但是运行结果是57,然后在尝试

intval(0.68*100)输出 68

intval(0.56*100)输出 56

intval(0.57*100)输出 56

intval(0.58*100)输出 57

intval(0.59*100)输出 59

为什么只是0.57*100和0.58*100会特殊呢?

首先我们来看intval()在PHP 的 Manual 里有写,是 intval() 这个函数的问题,采用的是“截断”法取整。

这个问题看似奇特,其实还是浮点数的精度的问题,0.58*100 的结果是什么?其实大家试试就知道了,并不是想象中的 58,而是 57.99999999999999,为什么会这样 我们先来说下计算机中保存浮点数 不能精确表示,本篇可能比较烧脑子,我会尽量用最通俗的语言,最贴近现实的例子来讲解,不在乎篇幅有多长,关键是要给大家讲明白。下一篇,你将了解到浮点数如何工作,以及为什么很多数 不能表示。

热身 —— 问:要把小数装入计算机,总共分几步?你猜对了,3 步。

• 第一步:转换成二进制

• 第二步:用二进制科学计算法表示

• 第三步:表示成 IEEE 754 形式

在上面的第一步和第三步都有可能 丢失精度。

下面我们讨论如何把十进制小数转换成二进制小数(什么?你不会?请自觉去面壁)。考虑我们将 1/7(七分之一) 写成小数的时候是如何做的?用 1 除以 7,得到的商就是小数部分,剩下的余数我们继续除以 7,一直除到什么时候结束呢? 有两种情况:

1. 如果余数为 0。yeah!终于结束了,洗洗睡吧

2. 当除到某一步时,余数等于 1… 停!stop!等一下,我发现有什么地方怪怪的。余数为 1,余数如果为 1 的话,再继续除下去,不就又是 1/7 了吗?绕了一个大弯,又回来了?对,你猜的很对,它永远不会结束,它循环了。注意我上面说的 情况2,我们判断他循环,并 不是从直观看感觉它重复了,而是因为在计算过程中,它又回到了开头。为什么这么说呢?当你计算一个分数时,它总是连续出现 5,出现了好多次,例如 0.5555555… 你也无法断定它是无限循环的,比如 一亿分之五

其实 0.58*100 = 57.99999999999999 是不局限于任何语言的,是 IEEE 规定的浮点数的运算标准。一般情况下,57.99999999999999 会四舍五入到 58。需要注意的是,浮点数的四舍五入和咱们普通的数学里面的也是不同的,浮点数遇到 5 后,不一定总是入,有时也舍,具体细节不多解释了。

为什么结果是 57 呢,主要是因为 intval 函数的规则是,从第一个数字开始,知道遇到不是数字的字符,结束。

猜你喜欢

转载自www.cnblogs.com/zhang0807/p/10581040.html
57