摘要:吐槽一句,大二的專業(yè)課數(shù)字邏輯電路終于用在工作上了。,整數(shù)位為,且精度只到十分位,因此是。如果是不限精度的話,轉(zhuǎn)換后的二進(jìn)制數(shù)應(yīng)該是無(wú)限循環(huán)。再看一下百科給出的標(biāo)準(zhǔn)因此,的類型,最高的位是符號(hào)位,接著的位是指數(shù),剩下的位為有效數(shù)字。
用一句話概括就是:
EcmaScrpt規(guī)范定義Number的類型遵循了IEEE754-2008中的64位浮點(diǎn)數(shù)規(guī)則定義的小數(shù)后的有效位數(shù)至多為52位導(dǎo)致計(jì)算出現(xiàn)精度丟失問題!
如果你看不懂這句話,仔細(xì)閱讀本篇博客就對(duì)了!
首先看下10進(jìn)制轉(zhuǎn)換為2進(jìn)制的方法。
數(shù)字邏輯電路上的算法是 (0.1)10 = (0.0)2。
吐槽一句,大二的專業(yè)課數(shù)字邏輯電路終于用在工作上了。
0.1*2 = 0.2 ,整數(shù)位為0,且精度只到十分位,因此是0.0。
如果是不限精度的話,轉(zhuǎn)換后的二進(jìn)制數(shù)應(yīng)該是:0.000110011001100110011(0011)無(wú)限循環(huán)。
如果表示成一個(gè)奇怪的形式,則是 (-1)^0*1.100110011(0011)* 2^-4
上述式子可類比十進(jìn)制科學(xué)計(jì)數(shù)法公式。
0.0001234567 = 1.234567 * 10^-4?
為什么要這樣表示?
-1的0次冪又是什么意思?
這是國(guó)際標(biāo)準(zhǔn)組織IEEE754對(duì)于浮點(diǎn)數(shù)表示方式的一種定義。
格式為;
(-1)^S x Mx 2^E
各符號(hào)的意思如下:
S,是符號(hào)位,決定正負(fù),0時(shí)為正數(shù),1時(shí)為負(fù)數(shù)。
M,是指有效位數(shù),大于1小于2?!?br>E,是指數(shù)位。
因此才有了下面的形式:
(-1)^0*1.100110011(無(wú)限循環(huán)0011) * 2^-4 S = 0,M = 1.100110011(無(wú)限循環(huán)0011),E =-4
對(duì)應(yīng)的0.2為:
(-1)^0*1.100110011(無(wú)限循環(huán)0011) * 2^-3 S = 0 ,M = 1.100110011(無(wú)限循環(huán)0011),E =-3
那么這和javascript有什么關(guān)系呢?
因?yàn)镮EEE754標(biāo)準(zhǔn)里,還有兩種特殊的定義。
IEEE 754規(guī)定,對(duì)于32位的浮點(diǎn)數(shù),最高的1位是符號(hào)位S,接著的8位是指數(shù)E,剩下的23位為有效數(shù)字M。
對(duì)于64位的浮點(diǎn)數(shù),最高的1位是符號(hào)位S,接著的11位是指數(shù)E,剩下的52位為有效數(shù)字M。
問題還是一樣,這和我們的javascript有什么關(guān)系呢?
因?yàn)閖avascript中Number類型,就是嚴(yán)格按照IEEE754標(biāo)準(zhǔn)來定義的。下面給出了最新版的ecma-262版本中關(guān)于Number類型的定義。
*6.1.6
The Number Type**
The Number type has exactly 18437736874454810627 (that is,?) values, representing the double-precision 64-bit format IEEE 754-2008 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990 (that is,?) distinct “Not-a-Number” values of the IEEE Standard are represented in ECMAScript as a single special??value.
再看一下wiki百科給出的IEEE754標(biāo)準(zhǔn):
因此,javascript的Number類型, 最高的1位是符號(hào)位S,接著的11位是指數(shù)E,剩下的52位為有效數(shù)字M。
拿0.1舉例來說:
(-1)^01.100110011(無(wú)限循環(huán)0011) 2^-4
= 0,M = 1.100110011(無(wú)限循環(huán)0011),E =-4
這里的無(wú)限循環(huán)就有限了,循環(huán)位數(shù)最多只能有52位.
JS中的0.1,在引擎中運(yùn)算時(shí),實(shí)質(zhì)上會(huì)編譯成:
1.1001100110011001100110011001100110011001100110011001*2^-4
0.2同理,會(huì)編譯成:
1.1001100110011001100110011001100110011001100110011001*2^- 3
拿出關(guān)鍵的指數(shù)部分和有效位部分:
-4??0.1001100110011001100110011001100110011001100110011001 ① -3 ?0.1001100110011001100110011001100110011001100110011001 ②·
①式轉(zhuǎn)化為純小數(shù),小數(shù)最低位的1001被高位的0000擠出有效范圍,得到③式
②式轉(zhuǎn)化為純小數(shù),小數(shù)最低位的001被高位的000擠出有效范圍,得到④式
原因是什么?
原因就是JS中的Number類型,二進(jìn)制小數(shù)的有效位數(shù)只有52位,從0到51位(包括邊界)。
在chrome控制臺(tái)輸入(0.1).toString("2")并打印結(jié)果為:"0.0001100110011001100110011001100110011001100110011001101"
不多不少,小數(shù)部分剛好52位,與規(guī)范以及我們的猜想完全契合。
回到0.1+0.2===0.30000000000000004這個(gè)經(jīng)典問題。
在EcmaScript中,無(wú)關(guān)Browser環(huán)境,還是Nodejs環(huán)境,0.1+0.2的實(shí)際計(jì)算過程如下:
? ?? 0.0000100110011001100110011001100110011001100110011001 ③ ? ? +0.0001001100110011001100110011001100110011001100110011 ④ --------------------------------------------------------------------------------------------------- ? ? =0.0100110011001100110011001100110011001100110011001100 ⑤
最后得到的⑤式其實(shí)0.300000000000000004(17位十進(jìn)制數(shù))的二進(jìn)制形式。
這就是0.1+0.2 ===0.300000000000000004的原因。
雖然我們期望的理想結(jié)果是返回0.3,恰恰印證了現(xiàn)實(shí)往往很骨感的說法。
有沒有讓0.1+02返回為0.3的辦法呢?
因?yàn)椴恢皇沁@一個(gè)精度丟失特例,還有很多情況都會(huì)造成精度丟失,比如:
0.3 / 0.1===2.9999999999999996以及0.7 * 180==125.99999999998等等。
那么有沒有辦法解決這個(gè)問題呢?
移步下一篇博客:如何解決0.1 +0.2===0.30000000000000004類問題
鳴謝單位:
https://segmentfault.com/a/1190000005022170
http://demon.tw/copy-paste/javascript-precision.html
http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html
http://www.css88.com/archives/7340#more-7340
http://www.ecma-international.org/ecma-262/8.0/index.html
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Internal_representation
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89591.html
摘要:方法使用定點(diǎn)表示法來格式化一個(gè)數(shù),會(huì)對(duì)結(jié)果進(jìn)行四舍五入。該數(shù)值在必要時(shí)進(jìn)行四舍五入,另外在必要時(shí)會(huì)用來填充小數(shù)部分,以便小數(shù)部分有指定的位數(shù)。如果數(shù)值大于,該方法會(huì)簡(jiǎn)單調(diào)用并返回一個(gè)指數(shù)記數(shù)法格式的字符串。在環(huán)境中,只能是之間,測(cè)試版本為。 showImg(https://segmentfault.com/img/remote/1460000011913134?w=768&h=521)...
摘要:忍者級(jí)別的函數(shù)操作對(duì)于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對(duì)于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...
摘要:因此利用以及語(yǔ)法樹在代碼構(gòu)建過程中重寫等符號(hào),開發(fā)時(shí)直接以這樣的形式編寫代碼,在構(gòu)建過程中編譯成,從而在開發(fā)人員無(wú)感知的情況下解決計(jì)算失精的問題,提升代碼的可讀性。 前言 你了解過0.1+0.2到底等于多少嗎?那0.1+0.7,0.8-0.2呢? 類似于這種問題現(xiàn)在已經(jīng)有了很多的解決方案,無(wú)論引入外部庫(kù)或者是自己定義計(jì)算函數(shù)最終的目的都是利用函數(shù)去代替計(jì)算。例如一個(gè)漲跌幅百分比的一個(gè)...
摘要:簡(jiǎn)介是目前最流行的深度學(xué)習(xí)框架。代表一個(gè)數(shù)學(xué)運(yùn)算,簡(jiǎn)稱,這里面包括了深度學(xué)習(xí)模型經(jīng)常需要使用的。這也是名字的由來,表示多維數(shù)組在中流動(dòng)。這一步指定求解器,并設(shè)定求解器的最小化目標(biāo)為損失。 簡(jiǎn)介 TensorFlow是目前最流行的深度學(xué)習(xí)框架。我們先引用一段官網(wǎng)對(duì)于TensorFlow的介紹,來看一下Google對(duì)于它這個(gè)產(chǎn)品的定位。 TensorFlow? is an open sou...
閱讀 2225·2021-09-07 09:58
閱讀 3402·2019-08-30 14:07
閱讀 1310·2019-08-29 12:32
閱讀 677·2019-08-29 11:06
閱讀 3703·2019-08-26 18:18
閱讀 3742·2019-08-26 17:35
閱讀 1391·2019-08-26 11:35
閱讀 619·2019-08-26 11:35