眾所周知,浮點計算會產生舍入誤差的問題,比如,0.1+0.2,結果應該是0.3,但是計算的結果並不是如此,而是0.30000000000000004,這是使用基於IEEE754數值的浮點計算的通病,js並非獨此一家,今天我們就來看看js怎麼解決這個誤差的。
以下是針對加減乘除的解決方法:
加法:
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;
}
減法:
function accSub(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)); //last modify by deeka //動態控制精度長度
n = (r1 >= r2) ? r1 : r2; //取位數大的
// n = Math.max(r1, r2);
return ((arg1 * m - arg2 * m) / m).toFixed(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);
}
除法:
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) * pow(10, t2 - t1);
}
}
用以上4個方法進行計算的話,就能夠規避浮點數計算誤差問題了,他們的原理大多是,通過去掉小數點,將浮點數變為整數,再進行計算。比如加法:
var r1, r2, m, c; //r1為arg1的小數位數,r2為arg2的小數位數,m為arg1和arg2較大數的冪,c是位數差
try {
r1 = arg1.toString().split(".")[1].length; //計算arg1的位數
}
catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split(".")[1].length; //計算arg2的位數
}
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; //將擴大了的數相加,再除以較大數的冪,將結果還原
}
從上面可以看出,為了的到兩個小數擴大後的整數,使用的是現將他們轉換成字串,再用空去替換點號,這個方法得到的數字就是擴大後的數字,而網上流行另一種寫法,就是先乘以一個倍數,將其變為整數,再相加,再除以倍數的方法,這個方法乍一看,是行的通的,但是經過測試,此方法也會存在bug。
function add(a, b) {
var c, d, e, h;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
e = Math.pow(10, Math.max(c, d));
return (a * e + b * e) / e;
//h = Math.max(c, d);
//return ((mul(a, e) + mul(b, e)) / e).toFixed(h);
}
此方法e指的是兩個數中較大數的冪,錯就錯在,ae,和be在計算的時候會出現計算誤差,由於wiki不能上傳圖片,就不展示了,綜上所述,我推薦第一種的解決方案。當然第二種也是有不就措施的,就是將我上面程式碼的兩行註釋放開,我們運用了toFixed將誤差給擷取,從而得到正確的結果。
這裡,我在提供一個測試的方法:
function test() {
var a = (Math.random() * 100).toFixed(2) - 0;
var b = (Math.random() * 1000).toFixed(2) - 0;
var result = add(a, b);
if ((result + '').length > 10) {
console.error('被加數:' + a, '加數:' + b, '結果:' + result);
return;
}
setTimeout(function () {
test();
}, 10);
}
js處理浮點數計算誤差
相關文章
- 為什麼計算機對浮點型數字計算存在誤差計算機
- php 處理 浮點數 精度運算 數字處理等PHP
- js中浮點數計算常用方法JS
- js精確計算浮點數相加JS
- python處理浮點數Python
- Python浮點數(小數)運算誤差的原因和解決辦法Python
- 關於JS的浮點數計算精度問題解決方案JS
- LibBF——處理任意精度浮點數的小型庫
- 全面總結 JS 中浮點數運算問題JS
- 浮點數線上轉hex計算工具
- JS中如何理解浮點數?JS
- JavaScript浮點數加減乘除精確計算JavaScript
- 計算機組成原理浮點數加減計算機
- 浮點數在計算機底層的表示及運算計算機
- js浮點數丟失問題JS
- JS中浮點數精度問題JS
- 計算機組成與體系結構-數值表示範圍-浮點數計算計算機
- 計組之資料運算:9、浮點數的表示
- js計算圖片內點個數JS
- JavaScript解決浮點數算數運算精度問題JavaScript
- 06 Windows批處理之整數和浮點資料型別Windows資料型別
- js精確比較浮點數大小JS
- 圖解計算機中的數值範圍和浮點運算圖解計算機
- js錯誤處理權威指北JS
- 深入理解浮點數的運算
- 計算機組成與體系結構-浮點數表示計算機
- 二進位制轉float浮點數線上計算工具
- js浮點數儲存精度丟失原理JS
- 浮點數
- python中精確的浮點數運算Python
- Python做浮點數(float)運算要小心Python
- 浮點數的加減乘除運算細節
- 資料處理02:Python數值計算包NumPyPython
- 單像空間後方交會計算誤差方程係數矩陣矩陣
- go 錯誤處理設計思考Go
- webgl 影像處理 加速計算Web
- 計算機組成原理白學了,再次回顧浮點數加減計算機
- 計算機組成原理--浮點數-原碼補碼錶示範圍計算機