-
博文分类专栏
- Jquery基础教程
-
- 文章:(15)篇
- 阅读:46549
- shell命令
-
- 文章:(42)篇
- 阅读:154227
- Git教程
-
- 文章:(36)篇
- 阅读:234843
- leetCode刷题
-
- 文章:(76)篇
- 阅读:131787
-
PHP7中对大数求余报错Uncaught DivisionByZeroError: Modulo by zero2018-03-13 21:56 阅读(10954) 评论(2)
一、问题描述
今天在使用PHP中的求余的时候,发现了一个“很怪异的事”,
在PHP中执行如下代码
echo 2 % pow(2,32);
既然报错:
PHP Fatal error: Uncaught DivisionByZeroError: Modulo by zero in Command line code:1
Stack trace:
#0 {main}
thrown in Command line code on line 1
Fatal error: Uncaught DivisionByZeroError: Modulo by zero in Command line code:1
Stack trace:
#0 {main}
thrown in Command line code on line 1
换了台机器,既然能够执行成功,如下:
32位系统执行如下:
当在64位系统中,却能正常如下:
当时觉得不可以思议,最后好好比较了一下两台机器的区别,发现原来是一台32位,一台64位,于是就猜想可能是PHP整形溢出的问题。
通过查阅手册发现,原来PHP的int类型的字长
在32位系统上面,int是4个字节,取值范围为:-2147483648(231) ~ 2147483647(231 - 1)
在64位系统上面,int是8个字节,取值范围为:-2147483648(263) ~ 2147483647(263 - 1)
超过int范围,就会导致整型溢出,如下:
PHP官方手册上面说,超出整型int的表示范围,就会自动隐式地转为float类型。
故在32位操作系统上面232以float类型表示,可以在命令行中执行如下命令验证:
php -r '$a = pow(2,32); var_dump(is_float($a));'; //bool(true)
php在对数值取模运算时会把浮点数float隐式地转为int类型再取模,浮点数转换成整数时,将向下取整。
如果浮点数超出了整数范围,则结果为未定义,因为没有足够的精度给出一个确切的整数结果。在此情况下没有警告,甚至没有任何通知!
看来有时间得看看PHP源码了。当int类型溢出的时候,会变成什么数呢?这个问题回头得好好看看。
二、问题的解决
既然整型会溢出,那么,我们可以使用浮点型float类型,但是PHP在使用%运算符的时候,会隐式地转为int类型,怎么办呢?这时候,fmod函数派上了用场,语法如下:
float fmod ( float $x , float $y )
对超过php的int类型取余,可以使用如下方面:
var_dump(fmod(14, pow(2,32))); //14
三、类似问题
1、数字和字符串的比较
首先,来看看个案例,如下:
var_dump(in_array(0, [3,"a", 6, "b"])); var_dump(array_search(0, [3,"a", 6, "b"])); var_dump(0 == 'a'); var_dump(in_array('dequan', [true, 'de', 'quan']));
执行结果如下:
为什么都是ture?
关键在于比较前,php做了类型转换。
2、php中浮点数精度问题
其实,所谓的诡异,往往源自于知识的缺乏。