如果用PHP的算术计算浮点数的时候,可能会遇到一些计算结果错误的问题
<?php $a = 0.1; $b = 0.7; var_dump(($a + $b) == 0.8); //false $f = 0.58; var_dump(intval($f * 100)); //为啥输出57
解决方案:安装bcmath这个扩展
bcadd — 将两个高精度数字相加
bccomp — 比较两个高精度数字,返回-1, 0, 1
bcdiv — 将两个高精度数字相除
bcmod — 求高精度数字余数
bcmul — 将两个高精度数字相乘
bcpow — 求高精度数字乘方
bcpowmod — 求高精度数字乘方求模,数论里非常常用
bcscale — 配置默认小数点位数
bcsqrt — 求高精度数字平方根
bcsub — 将两个高精度数字相减 php保留两位小数,但不四舍五入
/** * 保留小数点后几位,并且不四舍五入 * $bcscale 保留位数,默认2位 */ function number_float_format($number, $bcscale = 2) { $tmp_bcscale = $bcscale + 1; return sprintf("%.{$bcscale}f", substr(sprintf("%.{$tmp_bcscale}f", $number), 0, -1)); }JS浮点数精确计算函数(加,减,乘,除)
<script type="text/javascript"> var Digit = {}; /** * 四舍五入法截取一个小数 * @param float digit 要格式化的数字 * @param integer length 要保留的小数位数 * @return float */ Digit.round = function (digit, length) { length = length ? parseInt(length) : 0; if (length <= 0) return Math.round(digit); digit = Math.round(digit * Math.pow(10, length)) / Math.pow(10, length); return digit; }; /** * 舍去法截取一个小数Digit.floor(1.653,2) * @param float digit 要格式化的数字 * @param integer length 要保留的小数位数 * @return float */ Digit.floor = function (digit, length) { length = length ? parseInt(length) : 0; if (length <= 0) return Math.floor(digit); digit = Math.floor(digit * Math.pow(10, length)) / Math.pow(10, length); return digit; }; /** * 进一法截取一个小数 * @param float digit 要格式化的数字 * @param integer length 要保留的小数位数 * @return float */ Digit.ceil = function (digit, length) { length = length ? parseInt(length) : 0; if (length <= 0) return Math.ceil(digit); digit = Math.ceil(digit * Math.pow(10, length)) / Math.pow(10, length); return digit; } //浮点数加法运算 Digit.add = function (arg1, arg2) { var r1, r2, m; try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} m = Math.pow(10, Math.max(r1, r2)) return (arg1 * m + arg2 * m) / m } //浮点数减法运算 Digit.sub = function (arg1, arg2) { var r1, r2, m, n; try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} m = Math.pow(10, Math.max(r1, r2)); //动态控制精度长度 n = (r1 >= r2) ? r1 : r2; return ((arg1 * m - arg2 * m) / m).toFixed(n); } //浮点数乘法运算 Digit.mul = function (arg1, arg2) { var m = 0, s1 = arg1.toString(), s2 = arg2.toString(); try{m+=s1.split(".")[1].length}catch(e){} try{m+=s2.split(".")[1].length}catch(e){} return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m) } //浮点数除法运算 Digit.div = function (arg1, arg2) { var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].length}catch(e){} try{t2=arg2.toString().split(".")[1].length}catch(e){} with(Math){ r1 = Number(arg1.toString().replace(".", "")) r2 = Number(arg2.toString().replace(".", "")) return (r1 / r2) * pow(10, t2 - t1); } } /** 这个函数可以添加分隔逗号或者进行四舍五入。 * Usage: (123456.789).number_format(2, '.', ','); * result: 123,456.79 **/ Number.prototype.number_format = function (decimals, decimal_sep, thousands_sep) { var n = this, c = isNaN(decimals) ? 2 : Math.abs(decimals), d = decimal_sep || '.', t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, sign = (n < 0) ? '-' : '', i = parseInt(n = Math.abs(n).toFixed(c)) + '', j = ((j = i.length) > 3) ? j % 3 : 0; return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); } /* 给数字添加"st, nd, rd, th"等序数词。 * Usage: * var myNumOld = 23 * var myNumNew = myNumOld.toOrdinal() * Result: 23rd */ Number.prototype.toOrdinal = function () { var n = this % 100; var suffix = ['th', 'st', 'nd', 'rd', 'th']; var ord = n < 21 ? (n < 4 ? suffix[n] : suffix[0]) : (n % 10 > 4 ? suffix[0] : suffix[n % 10]); return this + ord; } </script>