• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

php中小数精度的代码解析

php 搞代码 3年前 (2022-01-21) 20次浏览 已收录 0个评论

本篇文章给大家带来的内容是关于php中小数精度的代码解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

项目中保留两位小数四舍五入遇到精度问题:

$num = 0.99;$num1 = round($num, 2);//0.98999999999999999$num2 = floatval($num);//0.98999999999999999

目前解决方案:

sprintf("%.2f", round($money, 2));//会自动四舍五入echo substr(sprintf("%.3f",$n), 0, -1);//不四舍五入

测试结果:

var_dump(json_encode(round(0.99 ,2)));//0.98999999999999999var_dump(round(0.99 ,2));//0.99$f = 0.58;    var_dump(intval($f * 100));//57

关于等于57这个问题,我们可以分析一下:

浮点数的表示(IEEE 754:IEEE二进位浮点数算术标准):

  浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).

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

  指数位:表示数据以2为底的幂,指数采用偏移码表示

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

0.58 对于二进制表示来说, 是无限长的值:

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

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

而两者的二进制, 如果只是通过这52位计算的话,分别是:

   0.58 –> 0.57999999999999996

0.57 –> 0.5699999999999999

所以,0.58 * 100 结果会:57.999999999,转成整型:57

关于浮点数的二进制表示可以参考:浮点数的二进制表示

类似:

(0.1 + 0.7) == 0.8//falsefloor((0.1+0.7)*10)//7 //内部结果可能是:7.9999999999//所以:不可能精确的用有限位数表达某些十进制分数1/3=3.33333333333//而3.333333333333333*3,却不是1

所以结论:

所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数

建议使用高精度函数:

高精度函数

  • bcadd — 2个任意精度数字的加法计算

  • bccomp — 比较两个任意精度的数字

  • bcp — 2个任意精度的数字除法计算

  • bcmod — 对一个任意精度数字取模

  • bcmul — 2个任意精度数字乘法计算

  • bcpow — 任意精度数字的乘方

  • bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus

  • bcscale — 设置所有bc数学函数的默认小数点保留位数

  • bcsqrt — 任意精度数字的二次方根

  • bcsub — 2个任意精度数字的减法

使用高精度函数实现四舍五入:

    function getBcRound($number, $precision = 0)    {        $precision = ($precision < 0)                   ? 0                   : (int) $precision;        if (strcmp(bcadd($number, '0', $precision), bcadd($number, '0', $precision+1)) == 0) {            return bcadd($number, '0', $precision);        }        if (getBcPresion($number) - $precision > 1) {            $number = getBcRound($number, $precision + 1);        }        $t = '0.' . str_repeat('0', $precision) . '5';        return $number < 0               ? bcsub($number, $t, $precision)               : bcadd($number, $t, $precision);    }        function getBcPresion($number) {        $dotPosition = strpos($number, '.');        if ($dotPosition === false) {            return 0;        }        return strlen($<i>1本文来#源gaodai$ma#com搞$代*码*网</i><pre>搞代gaodaima码

number) – strpos($number, '.') – 1; } $money = getBcRound(0.99, 2);

相关文章推荐:

PHP中AES加密文件的解析(附代码)

php的curl中post方式和get方式的请求代码

关于PHP中间键的内容解析

以上就是php中小数精度的代码解析的详细内容,更多请关注搞代码gaodaima其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:php中小数精度的代码解析

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址