摘要:基于這個(gè)問題運(yùn)動(dòng)基礎(chǔ)問題,我想應(yīng)該也有一部分人沒有認(rèn)真對(duì)待過中浮點(diǎn)數(shù)的四則運(yùn)算出現(xiàn)的問題。解決方案引自解決方案為了解決浮點(diǎn)數(shù)運(yùn)算不準(zhǔn)確的問題,在運(yùn)算前我們把參加運(yùn)算的數(shù)先升級(jí)的的次方到整數(shù),等運(yùn)算完后再降級(jí)的的次方。
基于這個(gè)問題:javascript運(yùn)動(dòng)基礎(chǔ)問題 ,我想應(yīng)該也有一部分人沒有認(rèn)真對(duì)待過js中浮點(diǎn)數(shù)的四則運(yùn)算出現(xiàn)的問題。
1.問題描述示例代碼: var x = 0.3 - 0.2; //30美分減去20美分 var y = 0.2 - 0.1; //20美分減去10美分 x == y; // =>false,兩值不相等 x == 0.1; // =>false,真實(shí)值為:0.09999999999999998 y == 0.1; // =>true 這個(gè)問題并不只是在Javascript中才會(huì)出現(xiàn),任何使用二進(jìn)制浮點(diǎn)數(shù)的編程語言都會(huì)有這個(gè)問題,只不過在 C++/C#/Java 這些語言中已經(jīng)封裝好了方法來避免精度的問題,而 JavaScript 是一門弱類型的語言,從設(shè)計(jì)思想上就沒有對(duì)浮點(diǎn)數(shù)有個(gè)嚴(yán)格的數(shù)據(jù)類型,所以精度誤差的問題就顯得格外突出。2.產(chǎn)生原因
Javascript采用了IEEE-745浮點(diǎn)數(shù)表示法(幾乎所有的編程語言都采用),這是一種二進(jìn)制表示法,可以精確地表示分?jǐn)?shù),比如1/2,1/8,1/1024。遺憾的是,我們常用的分?jǐn)?shù)(特別是在金融的計(jì)算方面)都是十進(jìn)制分?jǐn)?shù)1/10,1/100等。二進(jìn)制浮點(diǎn)數(shù)表示法并不能精確的表示類似0.1這樣 的簡單的數(shù)字,上訴代碼的中的x和y的值非常接近最終的正確值,這種計(jì)算結(jié)果可以勝任大多數(shù)的計(jì)算任務(wù):這個(gè)問題也只有在比較兩個(gè)值是否相等時(shí)才會(huì)出現(xiàn)。
javascript的未來版本或許會(huì)支持十進(jìn)制數(shù)字類型以避免這些舍入問題,在這之前,你更愿意使用大整數(shù)進(jìn)行重要的金融計(jì)算,例如,要使用整數(shù)‘分’而不是使用小數(shù)‘元’進(jìn)行貨比單位的運(yùn)算---------以上整理自《Javascript權(quán)威指南P37》
首先,我們要站在計(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))
雙精度浮點(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ù)運(yùn)算不準(zhǔn)確的問題,在運(yùn)算前我們把參加運(yùn)算的數(shù)先升級(jí)(10的X的次方)到整數(shù),等運(yùn)算完后再降級(jí)(0.1的X的次方)。
//加法 Number.prototype.add = function(arg){ var r1,r2,m; try{r1=this.toString().split(".")[1].length}catch(e){r1=0} try{r2=arg.toString().split(".")[1].length}catch(e){r2=0} m=Math.pow(10,Math.max(r1,r2)) return (this*m+arg*m)/m } //減法 Number.prototype.sub = function (arg){ return this.add(-arg); } //乘法 Number.prototype.mul = function (arg) { var m=0,s1=this.toString(),s2=arg.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) } //除法 Number.prototype.div = function (arg){ var t1=0,t2=0,r1,r2; try{t1=this.toString().split(".")[1].length}catch(e){} try{t2=arg.toString().split(".")[1].length}catch(e){} with(Math){ r1=Number(this.toString().replace(".","")) r2=Number(arg.toString().replace(".","")) return (r1/r2)*pow(10,t2-t1); } }
ok,就是這樣了,大家以后在自己的代碼中遇到浮點(diǎn)數(shù)要想起js運(yùn)算的這樣的一個(gè)特性,避免不必要的錯(cuò)誤!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85567.html
摘要:原因至于問題產(chǎn)生的原因,或者關(guān)于問題的更詳細(xì)的描述,大家請(qǐng)看下面幾個(gè)文章浮點(diǎn)運(yùn)算浮點(diǎn)值運(yùn)算舍入誤差基礎(chǔ)浮點(diǎn)數(shù)四則運(yùn)算精度丟失問題解決方案這里主要討論一下解決方案的問題,上面幾篇文章的解決思路,都是重寫加法減法乘法和除法運(yùn)算。 問題背景 在 chrome 瀏覽器中調(diào)出開發(fā)者工具,在控制臺(tái)窗口輸入下面的表達(dá)式: 0.1 + 0.2 // 期望:0.3,結(jié)果:0.300...
摘要:如題先陳述下問題背景偶爾測(cè)測(cè)自己寫的計(jì)算器,隨便輸入玩嘛,然后發(fā)生下面詭異的事情當(dāng)我從一個(gè)輸入到十個(gè)的時(shí)候,過程顯示都是正確的,像這樣繼續(xù)輸入一個(gè)的時(shí)候,然后就這個(gè)樣子了什么原因呢看了下自己的代碼,代碼重要部分長這樣的這里用了一下強(qiáng)制轉(zhuǎn)化為 如題 先陳述下問題背景 偶爾測(cè)測(cè)自己寫的計(jì)算器,隨便輸入玩嘛,然后發(fā)生下面詭異的事情:當(dāng)我從一個(gè) 1 輸入到十個(gè) 1 的時(shí)候,過程顯示都是正確的...
摘要:浮點(diǎn)數(shù)并不是能夠精確表示范圍內(nèi)的所有數(shù)的,雖然浮點(diǎn)型的范圍看上去很大。但其實(shí)浮點(diǎn)數(shù)在保存數(shù)字的時(shí)候做了規(guī)格化處理,以進(jìn)制為例小數(shù)點(diǎn)前只需要保留位數(shù)對(duì)于二進(jìn)制來說,小數(shù)點(diǎn)前保留一位,規(guī)格化后始終是節(jié)省了,這個(gè)并不需要保存。 JS 中的最大安全整數(shù)是多少? JS 中所有的數(shù)字類型,實(shí)際存儲(chǔ)都是通過 8 字節(jié) double 浮點(diǎn)型 表示的。浮點(diǎn)數(shù)并不是能夠精確表示范圍內(nèi)的所有數(shù)的, 雖然 ...
摘要:本文通過介紹的二進(jìn)制存儲(chǔ)標(biāo)準(zhǔn)來理解浮點(diǎn)數(shù)運(yùn)算精度問題,和理解對(duì)象的等屬性值是如何取值的,最后介紹了一些常用的浮點(diǎn)數(shù)精度運(yùn)算解決方案。浮點(diǎn)數(shù)精度運(yùn)算解決方案關(guān)于浮點(diǎn)數(shù)運(yùn)算精度丟失的問題,不同場景可以有不同的解決方案。 本文由云+社區(qū)發(fā)表 相信大家在平常的 JavaScript 開發(fā)中,都有遇到過浮點(diǎn)數(shù)運(yùn)算精度誤差的問題,比如 console.log(0.1+0.2===0.3)// fa...
摘要:前言最近,朋友問了我這樣一個(gè)問題在中的運(yùn)算結(jié)果,為什么是這樣的雖然我告訴他說,這是由于浮點(diǎn)數(shù)精度問題導(dǎo)致的。由于可以用階碼移動(dòng)小數(shù)點(diǎn),因此稱為浮點(diǎn)數(shù)。它的實(shí)現(xiàn)遵循標(biāo)準(zhǔn),使用位精度來表示浮點(diǎn)數(shù)。 showImg(https://segmentfault.com/img/remote/1460000018981071); 前言 最近,朋友 L 問了我這樣一個(gè)問題:在 chrome 中的運(yùn)算...
閱讀 2397·2021-11-24 10:26
閱讀 2586·2021-11-16 11:44
閱讀 1704·2021-09-22 15:26
閱讀 3584·2021-09-10 11:11
閱讀 3191·2021-09-07 10:25
閱讀 3631·2021-09-01 10:41
閱讀 1015·2021-08-27 13:11
閱讀 3513·2021-08-16 11:02