分享编程~
 

PHP加减乘除精确计算函数bcadd,bcsub,bcmul,bcdiv,bcmod,bccomp

php在进行浮点数计算时结果并不一定是精确到了最后一位,intval(0.58*100) 输出 57 而不是58的问题原因以及php精确计算函数的应用bcadd,bcsub,bcmul,bcdiv,bcmod,bccomp

天天特卖抢好货

php在进行浮点数计算时结果并不一定是精确到了最后一位。

例一:

<?php 
$a =0.1;
$b = 0.7;
var_dump(($a + $b) == 0.8);
//打印的结果竟然是boolean false

例二:

<?php
intval(0.68*100)输出 68
intval(0.56*100)输出 56
intval(0.57*100)输出 56
intval(0.58*100)输出 57
intval(0.59*100)输出 59

上边例二中只是0.57*100和0.58*100会特殊?

因为计算机中保存浮点数不能精确表示,以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118…

intval(0.58*100); 存储的并不是58而是 57.99999999999999…,这不局限于任何语言的,是 IEEE 规定的浮点数的运算标准。

一般情况下,57.99999999999999 会四舍五入到 58。浮点数的四舍五入和普通的数学里面的有时候不一样,浮点数遇到 5 后,不一定总是入,有时也会舍,intval 函数的规则是,从第一个数字开始,直到遇到不是数字的字符结束,intval是截取了,一般解决方法是让计算后的值先转为字符串,再对字符串转整型:intval(strval(0.58*100));这样结果为58。

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

比如PHP中的,加:bcadd,减:bcsub,乘:bcmul,除:bcdiv,求余/取模:bcmod,:比较大小:bccomp。

例一可以转换为:

<?php
$a = 0.1;
$b = 0.7;
var_dump(bcadd($a,$b,2) == 0.8);
// 打印结果boolean true

例二转换为:intval(bcmul(0.58,100));

函数应用:

<?php
/**
 * 精确加法
 * @param [type] $a [description]
 * @param [type] $b [description]
 */
function math_add($a,$b,$scale = '2') {
	return bcadd($a,$b,$scale);
}


/**
 * 精确减法
 * @param [type] $a [description]
 * @param [type] $b [description]
 */
function math_sub($a,$b,$scale = '2') {
	return bcsub($a,$b,$scale);
}

/**
 * 精确乘法
 * @param [type] $a [description]
 * @param [type] $b [description]
 */
function math_mul($a,$b,$scale = '2') {
	return bcmul($a,$b,$scale);
}

/**
 * 精确除法
 * @param [type] $a [description]
 * @param [type] $b [description]
 */
function math_div($a,$b,$scale = '2') {
	return bcdiv($a,$b,$scale);
}

/**
 * 精确求余/取模
 * @param [type] $a [description]
 * @param [type] $b [description]
 */
function math_mod($a,$b) {
	return bcmod($a,$b);
}

/**
 * 比较大小
 * @param [type] $a [description]
 * @param [type] $b [description]
 * 大于 返回 1 等于返回 0 小于返回 -1
 */
function math_comp($a,$b,$scale = '5') {
	return bccomp($a,$b,$scale); // 比较到小数点位数
}


echo math_add('3.445','3.444')."\n"; // 加 6.88
echo math_sub('3.445','3.444')."\n"; // 减 0.00
echo math_mul('3.445','3.444')."\n"; // 乘 11.86
echo math_div('3.445','3.444')."\n"; // 除 1.00
echo math_mod('3.445','3.444')."\n"; // 取模 0
echo math_comp('3.445','3.444')."\n";// 比较 1

echo math_add('3.445','3.444','3')."\n"; // 加 6.889
echo math_sub('3.445','3.444','3')."\n"; // 减 0.001
echo math_mul('3.445','3.444','3')."\n"; // 乘 11.864
echo math_div('3.445','3.444','3')."\n"; // 除 1.000
echo math_mod('3.445','3.444')."\n"; // 取模 0
echo math_comp('3.445','3.444')."\n";// 比较 1


上一篇:TP5配置路由Route报致命错误:Call to a member function check() on string下一篇:常用sql语句操作数据库表字段查询笔记
赞(1) 踩(0)
您说多少就多少,您的支持是我最大的动力
赏金
微 信
赏金
支付宝
本文连接: https://www.yj521.com/article/213.html
版权声明: 本文为原创文章,版权归《越加网》所有,分享转载请注明出处!