php中小数精度的代码解析
内容导读
收集整理的这篇技术教程文章主要介绍了php中小数精度的代码解析,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2891字,纯文字阅读大概需要5分钟。
内容图文
本篇文章给大家带来的内容是关于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($number) - strpos($number, '.') - 1; } $money = getBcRound(0.99, 2);
相关文章推荐:
PHP中AES加密文件的解析(附代码)
php的curl中post方式和get方式的请求代码
关于PHP中间键的内容解析
以上就是php中小数精度的代码解析的详细内容,更多请关注Gxl网其它相关文章!
内容总结
以上是为您收集整理的php中小数精度的代码解析全部内容,希望文章能够帮你解决php中小数精度的代码解析所遇到的程序开发问题。 如果觉得技术教程内容还不错,欢迎将网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。