我们已经准备好了,你呢?

2024我们与您携手共赢,为您的企业形象保驾护航!

本文主要介绍PHP浮点数你应该知道的知识,本文讲解了PHP浮点数,PHP数的临界值,精度损失等问题,有需要的朋友可以参考一下。

PHP 是弱类型语言,这个特性要求无缝透明的隐式类型转换,PHP 使用 zval 来存储任意类型的值,zval 的结构如下(以 5.2 为例):

代码如下:

{

/* */

值;/* 值 */

类型;/* 类型 */

};

在上面的结构中,联合实际上存储了值本身:

代码如下:

联合 {

long lval; /* 长值 */

dval; /* 值 */

{

字符*val;

int 长度;

} 字符串;

*ht; /* 哈希表值 */

对象;

};

今天我们只讨论两个成员,lval 和 dval。我们应该意识到 long lval 的长度是可变的,取决于编译器和操作系统的字长。可能是或,而 dval(双精度)是 IEEE 754 规定的固定长度。必须是。

请记住这一点,因为这会使一些 PHP 代码“不独立于平台”。在下面的讨论中,除非另有说明,我们假设 long 是

这里就不引用IEEE 754浮点数的表示方法了,有兴趣的可以自己去查一下,重点是的尾数是52位存储的,包括隐藏的1个有效位,一共是。

这里就引出了一个很有意思的问题,我们以C代码为例(假设long为):

代码如下:

长a=x;

(a == (long) ()a);

请告诉我,当a的值在什么范围内时,上面的代码可以断言成功?(答案在文章最后)

现在让我们回到正题。在 PHP 执行脚本之前,它首先需要读取脚本并对其进行分析。此过程还包括对脚本中的文字进行 zval 处理。例如,对于以下脚本:

代码如下:

$a = ; // 64 位有符号数的最大值

$b = ; // 最大值 + 1

($a);

($b);

输出:

代码如下:

int()

浮点(9.+18)

也就是说在词法分析阶段,PHP 会判断某个字面量的值是否超出当前系统的长表值范围,如果不超出,则存放在 lval,zval 中,否则以 dval,zval 来表示。

我们必须小心任何大于最大整数值的值,因为它可能会失去精度:

代码如下:

$a = ;

$b = ;

($a === ($b - 1));

输出为错误。

现在我们继续开始的讨论,前面提到过,PHP 整数可以是 32 位,也可以是 64 位,这就意味着一些在 64 位系统上可以正常运行的代码,可能会因为不可见的类型转换而丢失精度,导致代码无法在 32 位系统上正常运行。

所以,我们必须警惕这个临界值,幸运的是,PHP 中已经定义了这个临界值:

代码如下:

回声;

当然,为了安全起见,我们应该使用字符串来存储大整数,并使用诸如这样的数学库来执行计算。

另外还有一个可能让我们比较困惑的关键配置就是php,这个配置决定了PHP在输出浮点值的时候,输出多少位有效数字。

最后我们再回顾一下上面提出的问题,即长整型在转换为float型然后再转换回long型时,能够保证不损失精度的最大值是多少?

例如,对于整数,我们知道它的二进制表示形式为 101。现在,让我们将其右移两位至 1.01,丢弃高位隐含有效位 1,得到存储在中的二进制值 5:

代码如下:

0/*符号位*/ /*指数位*/

5 的二进制表示在尾数中保留完整,因此在这种情况下,转换回长整型时不会损失精度。

我们知道尾数用 52 位表示,并且包含隐含的前导 1,因此总精度为 53 位。所以我们还可以得出,如果长整数小于:

代码如下:

2^53 - 1 == 90991; //记住,我们现在假设它是一个长整数

那么,当发生 long->->long 值转换时,这个整数将不会丢失精度。

本文主要介绍PHP浮点精度问题总结,本文主要针对PHP浮点精度丢失问题,用三段文字从不同角度阐述了该问题产生的原因及解决方法,有需要的朋友可以参考下文

1.PHP浮点精度丢失问题

我们首先来看下面的代码:

代码如下:

$f = 0.57;

回声($f * 100);//56

结果可能会让你有点吃惊,PHP 遵循 IEEE 754 双精度:

浮点数具有 64 位双精度,由 1 个符号位 (E)、11 个指数位 (Q) 和 52 个尾数位 (M) 表示(共 64 位)。

符号位:最高位,表示数据的正值或负值,0表示正数,1表示负数。

指数位:表示数据是2的幂,指数用偏移码表示

尾数:表示数据小数点后的有效数字的位数。

让我们看一下小数在二进制中是如何表示的:

乘以2取整数,按顺序排列,即先将小数部分乘以2,再取整数部分,继续将剩余的小数部分乘以2,再取整数部分,将剩余的小数部分再乘以2,继续取小数部分。但是像0.57这样的小数,如果这样乘法,小数部分就不可能为0。有有效数字的小数,用二进制表示就是无限的。

0.57 的二进制表示基本上是(52位):

如果只有 52 位,则 0.57 => 0。

不难看出上述出乎意料的结果。

2. PHP 浮点数的精度

首先看一下问题:

代码如下:

$f = 0.58;

(($f * 100)); //为什么输出57呢?

相信很多同学都有过这样的疑问。

具体的原理可以看“鸟哥”的一篇文章,里面有详细的解释:PHP浮点数常见问题解答

那么如何避免这个问题呢?

方法有很多,这里介绍两种:

1.

代码如下:

(("%.10f",($a/$b)),0,-7);

2. 四舍五入(注意会进行四舍五入)

代码如下:

舍入($a/$b,3);

或者你还有更好的方法,也可以给我留言。

3. PHP浮点数常见问题解答

关于PHP的浮点数,我之前写过一篇文章:关于PHP中的浮点数全是“假”

然而,我忽略了一件事,也就是以下常见问题的答案:

代码如下:

$f = 0.58;

(($f * 100)); //为什么输出57呢?

为什么输出是 57?是 PHP 的 bug 吗?

我相信很多同学都有过这个疑问,因为有很多人问我类似的问题,更不用说经常有人问...

为了理解原因,我们首先需要知道浮点数的表示形式(IEEE 754):

例如,长度为 64 位(双精度)的浮点数将由 1 个符号位(E)、11 个指数位(Q)和 52 个尾数位(M)表示(共 64 位)。

符号位:最高位,表示数据的正值或负值,0表示正数,1表示负数。

指数位:表示数据是2的幂,指数用偏移码表示

尾数:表示数据小数点后的有效数字的位数。

这里重点是小数在二进制中的表示,具体小数如何表示可以百度一下,这里就不多说了,重点是0.58在二进制表示中是一个无穷大的值(以下数字都省略了隐含的1)。

0.58 的二进制表示基本上是(52位):

0.57 的二进制表示基本上是(52位):

两者的二进制如果仅通过这52位来计算的话,则是:

代码如下:

0.58 -> 0。

0.57 -> 0。

至于具体的浮点乘法 0.58 * 100,我们就不详细考虑了,有兴趣的可以看(point),我们只是做一个大概的心算...0.58 * 100 = 57。

那你自然就57了……

可以看出,这个问题的关键点是:“你看似有限的小数,在计算机的二进制表示中却是无限的”

所以,不要再认为这是一个 PHP 错误了,它就是这样的……

本文主要介绍PHP Hash算法:算法代码示例,本文直接给出了实现代码,需要的朋友可以参考一下。

最近在看一本书,里面提到了一些hash算法,印象最深的是当时还不是很理解,所以今天就写了个程序来验证一下。

首先是代码:

复制代码如下:

/**

* CRC32 哈希

* @参数$str

* @int

*/

($str)

crc32($str) >> 16 & ;

/**

*哈希

* @参数$str

* @int

*/

($str)

$哈希=0;

对于($i=0;$i

$hash += 33 * $hash + ord($str{$i});

$哈希&;

$n=10;

// 测试用例 1

$stat = 数组();

对于($i=0;$i

$str = (md5((true)), 0, 8);

$p = ($str) % $n;

如果(isset($stat[$p])){

$统计[$p]++;

}别的{

$统计[$p] = 1;

(统计)($stat);

// 测试用例 2

$stat = 数组();

对于($i=0;$i

$str = (md5((true)), 0, 8);

$p = ($str) % $n;

如果(isset($stat[$p])){

$统计[$p]++;

}别的{

$统计[$p] = 1;

(统计)($stat);

上面有两个测试用例,第一个是采用CRC32方法,第二个是算法实现。

影响:

结果显示两种算法不相上下(可能是数据来源的原因,md5只有0-f)。也有文章说CRC32分布更均匀(参考链接:)

但它很耗时,而CRC32的速度几乎是其两倍。

为什么是 33?

是质数,也是奇数,除了33,还有131,1313,5381等等,PHP内置的hash函数就是用5381,在“鸟哥”的一篇博文里也有提到。

二维码
扫一扫在手机端查看

本文链接:https://by928.com/1572.html     转载请注明出处和本文链接!请遵守 《网站协议》
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。

项目经理在线

我们已经准备好了,你呢?

2020我们与您携手共赢,为您的企业形象保驾护航!

在线客服
联系方式

热线电话

13761152229

上班时间

周一到周五

公司电话

二维码
微信
线