你应该知道PHP浮点知识。
复制代码代码如下所示:
结构_zval_struct {
变量信息
zvalue_value值; / * * /
zend_uint引用计数;
zend_uchar型活跃型; / * * /
zend_uchar is_ref;
};
在上述结构中,实际保存价值本身是zvalue_value财团:
复制代码代码如下所示:
_zvalue_value { typedef联盟
长语句长值; / * * /
双双双值; / * * /
struct {
字符*;
Int len;
STR };
哈希表*哈希表值; / * * /
zend_object_value obj;
zvalue_value };
今天,我们只关心两个成员,语句和dval,我们应该意识到长语句与操作系统的编译器,不同长度的字的长度,它可能是32bits或64比特,双双(双精度)的IEEE 754规定是固定的,一定是64bits。
请记住这一点,PHP的一些代码的非平台独立性。Our next discussion, in addition to the particular point, assumes that long is 64bits
这里没有引用IEEE 754的浮点计数方法。你可以饶有兴趣地看到它。关键的一点是,双尾数是52位和1位的保存,有效隐藏53bits ..
在这里,它引出了一个非常有趣的问题。我们使用的C代码示例(假设长64位):
复制代码代码如下所示:
长x;
断言(a =(long)(double)a);
当A的值在什么范围内时,可以断言上面的代码(在文章的结尾)。
现在让我们回到要点上来。在执行脚本之前,PHP首先需要读取脚本并分析脚本。在这个过程中,机制也用于在脚本中,翻译字面量为例,下面的脚本:
复制代码代码如下所示:
< PHP
$ = 922337203685477580;64位的符号数最多。
$ = 922337203685477580; / + +的最大值1
var_dump(美元);
var_dump($);
输出:
复制代码代码如下所示:
Int(922337203685477580)
浮(9.22337203685e + 18)
换句话说,PHP在词法分析阶段,对于一个文字值,它将决定它是否超过了当前系统长的表值范围。如果不是,它将保存的语句,变量是is_long,否则它将代表dval,zval is_float ..
对于任何大于最大整数值的值,我们都必须小心,因为它可能会失去精度:
复制代码代码如下所示:
< PHP
$ = 922337203685477580;
$ = 922337203685477580;
var_dump($ =($ 1));
输出为false。
现在在讨论之前,开始说,PHP是一个32位整数,可能也可能是64,然后决定一些代码可以正常运行在64位,可能是因为隐藏类型转换,导致精度损失,导致代码不能正常运行,在32上系统。
因此,我们必须谨慎对待这个临界值,但是我们已经在PHP中定义了这个临界值:
复制代码代码如下所示:
< PHP
回声php_int_max;
>
当然,为了保险起见,我们应该使用字符串来拯救大整数,用数学函数库如bcmath计算。
此外,还有另一个关键配置将混淆我们。这是php.precision配置,这就决定了有多少有效位当PHP输出另一个浮点值。
最后,让我们回到上面提出的问题,即整数的长和最大值,这样我们就可以保证在长时间转向后,我们会回到浮点数,并且不会丢失精确性。
例如,对于整数,我们知道它是二进制表示法,101,现在,让我们有权,转1.01,给出高隐式有效1,我们得到二进制值5的双倍存储:
复制代码代码如下所示:
0 / / / * 10000000001 *指标位* / 0100000000000000000000000000000000000000000000000000
5的二进制表示,在部分结束时是最不损坏的,在这种情况下,从双返回到长,没有精确的损失。
我们知道,双使用52位表示尾数计算隐含的前1,这是53位精度。然后,如果长的整数值小于,我们就可以得到这个值:
复制代码代码如下所示:
2 ^ 53 - 1 = = 9007199254740991; / /记住,我们现在假设64bits长
所以,这个整数,当长时间的数值转换为双>长时,就不会丢失精度。