国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

JavaScript解決浮點(diǎn)數(shù)計(jì)算不準(zhǔn)確問題的方法分析

2024-05-06 15:32:50
字體:
供稿:網(wǎng)友

本文實(shí)例講述了JavaScript解決浮點(diǎn)數(shù)計(jì)算不準(zhǔn)確問題的方法。分享給大家供大家參考,具體如下:

最近在學(xué)習(xí)electron框架,想利用這個(gè)框架做一個(gè)簡(jiǎn)單的計(jì)算器demo。當(dāng)我對(duì)小數(shù)進(jìn)行運(yùn)算時(shí),發(fā)現(xiàn)了一個(gè)問題。

0.1+0.2=?

輸出結(jié)果是:0.30000000000000004。

為什么會(huì)這樣呢?

其實(shí)對(duì)于浮點(diǎn)數(shù)的四則運(yùn)算,幾乎所有的編程語言都會(huì)有類似精度誤差的問題,只不過在 C++/C#/Java 這些語言中已經(jīng)封裝好了方法來避免精度的問題,而 JavaScript 是一門弱類型的語言,從設(shè)計(jì)思想上就沒有對(duì)浮點(diǎn)數(shù)有個(gè)嚴(yán)格的數(shù)據(jù)類型,所以精度誤差的問題就顯得格外突出。

首先我們分析一下為什么會(huì)出現(xiàn)這個(gè)精度誤差?

首先,我們要站在計(jì)算機(jī)的角度思考 0.1 + 0.2 這個(gè)看似小兒科的問題。我們知道,能被計(jì)算機(jī)讀懂的是二進(jìn)制,而不是十進(jìn)制,所以我們先把 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))

上面我們發(fā)現(xiàn)0.1和0.2轉(zhuǎn)化為二進(jìn)制之后,變成了一個(gè)無限循環(huán)的數(shù)字,這在現(xiàn)實(shí)生活中,無限循環(huán)我們可以理解,但計(jì)算機(jī)是不允許無限循環(huán)的,對(duì)于無限循環(huán)的小數(shù),計(jì)算機(jī)會(huì)進(jìn)行舍入處理。進(jì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。

知道了浮點(diǎn)數(shù)產(chǎn)生的原因,那么如何處理這個(gè)問題呢?

方法1:通過toFixed(num)方法來保留小數(shù)。因?yàn)檫@個(gè)方法是根據(jù)四舍五入來保留小數(shù)的,所以最后的計(jì)算結(jié)果不精確。

方法2:把要計(jì)算的數(shù)字升級(jí)(乘以10的n次冪)成計(jì)算機(jī)能夠精確識(shí)別的整數(shù),計(jì)算完以后再降級(jí),推薦使用這一種方法。具體代碼如下(主要有3個(gè)方法):

/*判斷obj是否為一個(gè)整數(shù)*/function isInteger(obj){  return Math.floor(obj) === obj;}/*** 將一個(gè)浮點(diǎn)數(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ù)點(diǎn)的下標(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);  //將浮點(diǎn)數(shù)轉(zhuǎn)化為整數(shù)  var intNum = parseInt(floatNum*time + 0.5,10);  console.log('intNum===='+intNum);  ret.times = time;  ret.num = intNum;  return ret;}/***進(jìn)行運(yùn)算*三個(gè)參數(shù)分別是要運(yùn)算的兩個(gè)數(shù)和運(yùn)算符*/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;  }}            
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 宜宾市| 雷山县| 洪泽县| 寿阳县| 云安县| 波密县| 酒泉市| 金昌市| 宜宾县| 章丘市| 昆山市| 华安县| 邹城市| 九台市| 时尚| 大同市| 怀宁县| 沁水县| 张掖市| 蓝田县| 长汀县| 乳源| 湖南省| 汉沽区| 灵宝市| 华阴市| 托里县| 辽中县| 荣成市| 高淳县| 盘锦市| 磐石市| 佛学| 亳州市| 屏边| 北流市| 吕梁市| 崇义县| 尼勒克县| 锡林浩特市| 南木林县|