js精準(zhǔn)計(jì)算
var numA = 0.1; var numB = 0.2; alert( numA + numB );
0.1 + 0.2 = 0.30000000000000004。
計(jì)算精度誤差問題(和二進(jìn)制相關(guān))。
對(duì)于浮點(diǎn)數(shù)的四則運(yùn)算,幾乎所有的編程語言都會(huì)有類似精度誤差的問題,只不過在 C++/C#/Java 這些語言中已經(jīng)封裝好了方法來避免精度的問題,而JavaScript是一門弱類型的語言,從設(shè)計(jì)思想上就沒有對(duì)浮點(diǎn)數(shù)有個(gè)嚴(yán)格的數(shù)據(jù)類型,所以精度誤差的問題就顯得格外突出。
我們先把 0.1 和 0.2 轉(zhuǎn)換成二進(jìn)制看看:
0.1 => 0.0001 1001 1001 1001…(無限循環(huán))
0.2 => 0.0011 0011 0011 0011…(無限循環(huán))
雙精度浮點(diǎn)數(shù)的小數(shù)部分最多支持 52 位,所以兩者相加之后得到這么一串 0.0100110011001100110011001100110011001100110011001100 因浮點(diǎn)數(shù)小數(shù)位的限制而截?cái)嗟亩M(jìn)制數(shù)字,這時(shí)候,我們?cè)侔阉D(zhuǎn)換為十進(jìn)制,就成了 0.30000000000000004。
如何解決呢?
首先將數(shù)乘以10的冪次方去掉小數(shù)位得到可以轉(zhuǎn)化二進(jìn)制的整數(shù),計(jì)算之后再還原。
/**
** 除法函數(shù),用來得到精確的除法結(jié)果
** 說明:JavaScript的除法結(jié)果會(huì)有誤差,在兩個(gè)浮點(diǎn)數(shù)相除的時(shí)候會(huì)比較明顯。這個(gè)函數(shù)返回較為精確的除法結(jié)果。
** 調(diào)用:accdiv(arg1,arg2)
** 返回值:arg1除以arg2的精確結(jié)果
**/
function accdiv(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) * Math.pow(10, t2 - t1);
}
}
/**
** 加法函數(shù),用來得到精確的加法結(jié)果
** 說明:javascript的加法結(jié)果會(huì)有誤差,在兩個(gè)浮點(diǎn)數(shù)相加的時(shí)候會(huì)比較明顯。這個(gè)函數(shù)返回較為精確的加法結(jié)果。
** 調(diào)用:accAdd(arg1,arg2)
** 返回值:arg1加上arg2的精確結(jié)果
**/
function accAdd(arg1, arg2) {
var r1, r2, m, c;
try {
r1 = arg1.toString().split(".")[1].length;
}
catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split(".")[1].length;
}
catch (e) {
r2 = 0;
}
c = Math.abs(r1 - r2);
m = Math.pow(10, Math.max(r1, r2));
if (c > 0) {
var cm = Math.pow(10, c);
if (r1 > r2) {
arg1 = Number(arg1.toString().replace(".", ""));
arg2 = Number(arg2.toString().replace(".", "")) * cm;
} else {
arg1 = Number(arg1.toString().replace(".", "")) * cm;
arg2 = Number(arg2.toString().replace(".", ""));
}
} else {
arg1 = Number(arg1.toString().replace(".", ""));
arg2 = Number(arg2.toString().replace(".", ""));
}
return (arg1 + arg2) / m;
}
/**
** 乘法函數(shù),用來得到精確的乘法結(jié)果
** 說明:javascript的乘法結(jié)果會(huì)有誤差,在兩個(gè)浮點(diǎn)數(shù)相乘的時(shí)候會(huì)比較明顯。這個(gè)函數(shù)返回較為精確的乘法結(jié)果。
** 調(diào)用:accMul(arg1,arg2)
** 返回值:arg1乘以 arg2的精確結(jié)果
**/
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);
}
以上就是js精準(zhǔn)計(jì)算的詳細(xì)內(nèi)容,更多關(guān)于js精準(zhǔn)計(jì)算的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript中高階函數(shù)的巧妙運(yùn)用
JavaScript中的高階函數(shù)是指可以接受其他函數(shù)作為參數(shù)或者返回一個(gè)函數(shù)作為結(jié)果的函數(shù),本文介紹了JS中一些高階函數(shù)的妙用,希望對(duì)大家有所幫助2023-05-05
js中幾種循環(huán)的退出方式實(shí)例總結(jié)
提到在一段程序中如果碰到需要終止,結(jié)束一個(gè)循環(huán),函數(shù)或者一段代碼,一般會(huì)想到以下這幾個(gè)關(guān)鍵字return、continue、break,這篇文章主要給大家介紹了關(guān)于js中幾種循環(huán)的退出方式,需要的朋友可以參考下2022-12-12
關(guān)于TypeScript中import JSON的正確姿勢(shì)詳解
2012年10月首度對(duì)外公布typescript(當(dāng)時(shí)已經(jīng)是0.7?的版本)同時(shí)開源,ts的編譯器是用js編寫的(后來改成ts?),可以在線編寫。下面這篇文章主要給大家介紹了關(guān)于TypeScript中import JSON的正確姿勢(shì),需要的朋友可以參考下。2017-07-07
Listloading.js移動(dòng)端上拉下拉刷新組件
這篇文章主要介紹了Listloading.js移動(dòng)端上拉下拉刷新組件的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08

