如果用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 — 將兩個高精度數字相減
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>