JavaScript解決浮點數(shù)計算不準(zhǔn)確問題的方法分析
本文實例講述了JavaScript解決浮點數(shù)計算不準(zhǔn)確問題的方法。分享給大家供大家參考,具體如下:
最近在學(xué)習(xí)electron框架,想利用這個框架做一個簡單的計算器demo。當(dāng)我對小數(shù)進行運算時,發(fā)現(xiàn)了一個問題。
0.1+0.2=?
輸出結(jié)果是:0.30000000000000004。
為什么會這樣呢?
其實對于浮點數(shù)的四則運算,幾乎所有的編程語言都會有類似精度誤差的問題,只不過在 C++/C#/Java 這些語言中已經(jīng)封裝好了方法來避免精度的問題,而 JavaScript 是一門弱類型的語言,從設(shè)計思想上就沒有對浮點數(shù)有個嚴(yán)格的數(shù)據(jù)類型,所以精度誤差的問題就顯得格外突出。
首先我們分析一下為什么會出現(xiàn)這個精度誤差?
首先,我們要站在計算機的角度思考 0.1 + 0.2 這個看似小兒科的問題。我們知道,能被計算機讀懂的是二進制,而不是十進制,所以我們先把 0.1 和 0.2 轉(zhuǎn)換成二進制看看:
0.1 => 0.0001 1001 1001 1001..(無限循環(huán))
0.2 => 0.0011 0011 0011 0011…(無限循環(huán))
上面我們發(fā)現(xiàn)0.1和0.2轉(zhuǎn)化為二進制之后,變成了一個無限循環(huán)的數(shù)字,這在現(xiàn)實生活中,無限循環(huán)我們可以理解,但計算機是不允許無限循環(huán)的,對于無限循環(huán)的小數(shù),計算機會進行舍入處理。進行雙精度浮點數(shù)的小數(shù)部分最多支持52位,所以兩者相加之后得到這么一串 0.0100110011001100110011001100110011001100110011001100 因浮點數(shù)小數(shù)位的限制而截斷的二進制數(shù)字,這時候,我們再把它轉(zhuǎn)換為十進制,就成了 0.30000000000000004。
知道了浮點數(shù)產(chǎn)生的原因,那么如何處理這個問題呢?
方法1:通過toFixed(num)方法來保留小數(shù)。因為這個方法是根據(jù)四舍五入來保留小數(shù)的,所以最后的計算結(jié)果不精確。
方法2:把要計算的數(shù)字升級(乘以10的n次冪)成計算機能夠精確識別的整數(shù),計算完以后再降級,推薦使用這一種方法。具體代碼如下(主要有3個方法):
/*判斷obj是否為一個整數(shù)*/
function isInteger(obj){
return Math.floor(obj) === obj;
}
/**
* 將一個浮點數(shù)轉(zhuǎn)換成整數(shù),返回整數(shù)和倍數(shù)
* 如 3.14 》》314 倍數(shù)是100
*
*/
function toInteger(floatNum){
var ret = {times:1,num:0};
//是整數(shù)
if(isInteger(floatNum)){
ret.num = floatNum;
return ret;
}
var strfi = floatNum + '';
//查找小數(shù)點的下標(biāo)
var dotPos = strfi.indexOf('.');
console.log('dotPos===='+dotPos);
//獲取小數(shù)的位數(shù)
var len = strfi.substr(dotPos+1).length;
console.log('len===='+len);
//Math.pow(10,len)指定10的len次冪。
var time = Math.pow(10,len);
//將浮點數(shù)轉(zhuǎn)化為整數(shù)
var intNum = parseInt(floatNum*time + 0.5,10);
console.log('intNum===='+intNum);
ret.times = time;
ret.num = intNum;
return ret;
}
/**
*進行運算
*三個參數(shù)分別是要運算的兩個數(shù)和運算符
*/
function operation(a,b,op){
var o1 = toInteger(a);
var o2 = toInteger(b);
var n1 = o1.num;
var n2 = o2.num;
var t1 = o1.times;
var t2 = o2.times;
var max = t1 > t2 ? t1 : t2;
var result = null;
switch(op){
case 'add':
if(t1 === t2){
result = n1 + n2;
}else if(t1 > t2){
result = n1 + n2 * (t1/t2);
}else{
result = n1 * (t2/t1) + n2;
}
return result / max;
break;
case 'subtract':
if(t1 === t2){
result = n1 - n2;
}else if(t1 > t2){
result = n1 - n2 * (t1/t2);
}else{
result = n1 * (t2/t1) - n2;
}
return result / max;
break;
case 'multiply':
result = (n1 * n2)/(t1 * t2);
return result;
break;
case 'divide':
result = (n1 / n2)/(t2 / t1);
return result;
break;
}
}
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《JavaScript數(shù)學(xué)運算用法總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript數(shù)組操作技巧總結(jié)》、《JavaScript事件相關(guān)操作與技巧大全》、《JavaScript操作DOM技巧總結(jié)》及《JavaScript字符與字符串操作技巧總結(jié)》
希望本文所述對大家JavaScript程序設(shè)計有所幫助。
- javascript將浮點數(shù)轉(zhuǎn)換成整數(shù)的三個方法
- 跟我學(xué)習(xí)javascript的浮點數(shù)精度
- 深入理解JavaScript中的浮點數(shù)
- JavaScript浮點數(shù)及運算精度調(diào)整詳解
- 詳解JS-- 浮點數(shù)運算處理
- 詳解JavaScript 浮點數(shù)運算的精度問題
- JS實現(xiàn)的進制轉(zhuǎn)換,浮點數(shù)相加,數(shù)字判斷操作示例
- JS中浮點數(shù)精度問題的分析與解決方法
- 處理JavaScript浮點數(shù)精度問題的解決方案
- JavaScript 浮點數(shù)精度問題小結(jié)
相關(guān)文章
layui 富文本圖片上傳接口與普通按鈕 文件上傳接口的例子
今天小編就為大家分享一篇layui 富文本圖片上傳接口與普通按鈕 文件上傳接口的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
javascript使用shift+click實現(xiàn)選擇和反選checkbox的方法
這篇文章主要介紹了javascript使用shift+click實現(xiàn)選擇和反選checkbox的方法,涉及javascript針對鍵盤按鍵的判斷及checkbox的操作技巧,需要的朋友可以參考下2015-05-05
WEB泡泡堂2.0(圖形界面+電腦對玩)(javascript)
WEB泡泡堂2.0(圖形界面+電腦對玩)(javascript)2007-01-01
javascript實現(xiàn)用戶點擊數(shù)量統(tǒng)計
本文主要javascript實現(xiàn)用戶點擊數(shù)量統(tǒng)計的方法進行詳細(xì)介紹,具有很好的參考價值,需要的朋友一起來看下吧2016-12-12
javascript游戲開發(fā)之《三國志曹操傳》零部件開發(fā)(二)人物行走的實現(xiàn)
上一講我們談到了如何讓靜態(tài)人物變?yōu)閯討B(tài),今天我們來談?wù)勅绾问谷宋镆苿?,感興趣的朋友可以了解下哦,順便鞏固一下animate方法的應(yīng)用,希望本文對你有所幫助2013-01-01

