最近項(xiàng)目中用到了浮點(diǎn)的乘法運(yùn)算绩郎,遇到了兩個(gè)問題,一個(gè)是運(yùn)算的結(jié)果出現(xiàn)了誤差萍启,另一個(gè)問題是運(yùn)算結(jié)果出現(xiàn)了科學(xué)計(jì)數(shù)法总珠,需要將科學(xué)計(jì)數(shù)法轉(zhuǎn)換成普通數(shù)字。下面我們一一來處理勘纯。
1局服、js浮點(diǎn)數(shù)做數(shù)學(xué)運(yùn)算的時(shí)候出現(xiàn)誤差
我們都知道在計(jì)算機(jī)中所有的運(yùn)算都是以二進(jìn)制的形式進(jìn)行的,所以浮點(diǎn)數(shù)在進(jìn)行數(shù)學(xué)運(yùn)算的時(shí)候也會(huì)先轉(zhuǎn)換成二進(jìn)制驳遵,但是浮點(diǎn)數(shù)轉(zhuǎn)換成二進(jìn)制的時(shí)候可能會(huì)有無限位淫奔,而IEEE 754 標(biāo)準(zhǔn)的 64 位雙精度浮點(diǎn)數(shù)的小數(shù)部分最多支持 53 位二進(jìn)制位,所以二進(jìn)制表示的浮點(diǎn)數(shù)本身就有誤差堤结,數(shù)學(xué)運(yùn)算之后同樣存在誤差唆迁。
那么,怎樣消除這種誤差呢竞穷?目前通用的方式是:
//乘法
function accMul(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);
}
原理就是將浮點(diǎn)數(shù)轉(zhuǎn)化正整數(shù)唐责,運(yùn)算之后再轉(zhuǎn)化成浮點(diǎn)數(shù)。下邊這邊文章有非常詳細(xì)的講解:JavaScript 浮點(diǎn)數(shù)運(yùn)算的精度問題瘾带。
2鼠哥、科學(xué)計(jì)數(shù)法轉(zhuǎn)換成普通數(shù)字
JavaScript在以下情景會(huì)自動(dòng)將數(shù)值轉(zhuǎn)換為科學(xué)計(jì)數(shù)法:
(1)小數(shù)點(diǎn)前的數(shù)字個(gè)數(shù)大于等于22位;
(2)小數(shù)點(diǎn)前邊是0看政,小數(shù)點(diǎn)后十分位(包含十分位)之后連續(xù)零的個(gè)數(shù)大于等于6個(gè)朴恳。
但是,我并不想以科學(xué)技術(shù)法的形式展示給用戶允蚣,于是找到了以下這個(gè)函數(shù)菜皂,并且做了逐行分析:
:function scientificToNumber(num) {
if(/\d+\.?\d*e[\+\-]*\d+/i.test(num)) { //正則匹配科學(xué)計(jì)數(shù)法的數(shù)字
var zero = '0', //
parts = String(num).toLowerCase().split('e'), //拆分成系數(shù)和指數(shù)
e = parts.pop(),//存儲(chǔ)指數(shù)
l = Math.abs(e), //取絕對(duì)值,l-1就是0的個(gè)數(shù)
sign = e/l, //判斷正負(fù)
coeff_array = parts[0].split('.'); //將系數(shù)按照小數(shù)點(diǎn)拆分
if(sign === -1) { //如果是小數(shù)
num = zero + '.' + new Array(l).join(zero) + coeff_array.join(''); //拼接字符串厉萝,如果是小數(shù)恍飘,拼接0和小數(shù)點(diǎn)
} else {
var dec = coeff_array[1];
if(dec) l = l - dec.length; //如果是整數(shù),將整數(shù)除第一位之外的非零數(shù)字計(jì)入位數(shù)谴垫,相應(yīng)的減少0的個(gè)數(shù)
num = coeff_array.join('') + new Array(l+1).join(zero); //拼接字符串章母,如果是整數(shù),不需要拼接小數(shù)點(diǎn)
}
}
return num;
}
通過這兩個(gè)方法可以解決項(xiàng)目中遇到的兩個(gè)問題翩剪,驗(yàn)證有效乳怎,在此記錄。