如果用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这个扩展
bc是Binary Calculator的缩写。bc*函数的参数都是操作数加上一个可选的 [int scale],比如string bcadd(string $left_operand, string $right_operand[, int $scale]), 如果scale没有提供,就用bcscale的缺省值。这里大数直接用一个由0-9组成的string表示, 计算结果返回的也是一个string。bcadd — 将两个高精度数字相加
bccomp — 比较两个高精度数字,返回-1, 0, 1
bcdiv — 将两个高精度数字相除
bcmod — 求高精度数字余数
bcmul — 将两个高精度数字相乘
bcpow — 求高精度数字乘方
bcpowmod — 求高精度数字乘方求模,数论里非常常用
bcscale — 配置默认小数点位数
bcsqrt — 求高精度数字平方根
bcsub — 将两个高精度数字相减
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;
- }
- //浮点数加法运算
- function FloatAdd(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
- }
- //浮点数减法运算
- function FloatSub(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);
- }
- //浮点数乘法运算
- function FloatMul(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)
- }
- //浮点数除法运算
- function FloatDiv(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>
MySQL对于浮点值,结果是不准确的:
- SELECT .1E0 + .2E0 = .3E0;
在MySQL 5.1中,对于DECIMAL列和准确值数值,采用了“半值向上舍入”规则。对于小数部分等于或大于0.5的值,以0为分界舍入至最近的整数