數(shù)字作為語言的基礎(chǔ)十分重要,JS也一樣。JS中的數(shù)字只有一種就是雙精度浮點數(shù)搓幌。看ES文檔的時候發(fā)現(xiàn)一個奇怪的問題迅箩,JS中可以表示的數(shù)字是有限的溉愁!于是產(chǎn)生了一系列的疑問:JS中到底有多少個數(shù)字?JS中的數(shù)字最小值是多少饲趋?最大值呢拐揭?JS精確度又是多少?下面一一來說說奕塑。
JS中到底有多少個數(shù)字堂污?
文檔的回答是:2的64次方減去2的53次方再加三。這是怎么計算的呢龄砰?繼續(xù)往下看:后面的加3是三個特殊的數(shù)字正無窮盟猖,負(fù)無窮和NAN。剩下的還要去除兩個特殊的數(shù)字正零和負(fù)零换棚,剩下要從雙精度浮點數(shù)的規(guī)范IEEE754講起式镐,規(guī)范規(guī)定了雙精度浮點數(shù)是64位的,第1位為符號位表示正負(fù)固蚤,第2位到12位為指數(shù)位表示以2為基底的指數(shù)值碟案,剩下的52位為小數(shù)位或分?jǐn)?shù)位。所有的值可以分為10類的值颇蜡,其中四種是NaN類型的价说,剩下的6種正負(fù)各四種以0為原點對稱分布,以正數(shù)(符號位為0)為例:
1.指數(shù)位全0风秤,分?jǐn)?shù)位全0:表示正無窮鳖目;
2.指數(shù)位全0,分?jǐn)?shù)位非全0并且以0為虛擬的分?jǐn)?shù)首位(所以分?jǐn)?shù)共53位):表示正非規(guī)范數(shù)值缤弦;
3.指數(shù)位非全0非全1领迈,分?jǐn)?shù)位任意值并且以1為虛擬的分?jǐn)?shù)首位(所以分?jǐn)?shù)共53位):表示正規(guī)范數(shù)值;
正數(shù)共有:1 + Math.pow(2,52) - 1 + (Math.pow(2, 11) - 1) * (Math.pow(2, 52)) = Math.pow(2, 63) - Math.pow(2, 52)
加上負(fù)數(shù)的所有共有:Math.pow(2, 64) - Math.pow(2, 53)
補充:當(dāng)指數(shù)全1時為NaN值,但是ES規(guī)范規(guī)定NaN只有一個值狸捅,且任意兩個NaN不做區(qū)分衷蜓,且不相等。
JS中最大值和最小值尘喝?
此處的最大值和最小值是取絕對值的磁浇,且不包含極值0和正無窮。最大值好研究當(dāng)然是分?jǐn)?shù)位取最大值約為2朽褪,乘以指數(shù)位最大值Math.pow(2, 1023)置吓,也就是略小于Math.pow(2, 1024),因為此值包括更大的值會當(dāng)做正無窮缔赠。最小值出現(xiàn)在上述的情況2中:分?jǐn)?shù)位最后一位為1衍锚,指數(shù)位為最后一位為1偏移1023后得到-1022,所以相乘得到最小值:Math.pow(2,-1074) == 5e-324 嗤堰。
補充:Math.pow(2,-1075)仍可得出此值戴质,但已經(jīng)沒有太大意義,以為此值已經(jīng)極小且精確度因為非零開始的分?jǐn)?shù)位減少而降低踢匣。
JS精確度是多少置森?
通過第一個問題我們知道了基于二進(jìn)制的雙精度浮點數(shù)并不能全部映射到整個實數(shù)范圍,實際上差的甚遠(yuǎn)符糊。即便是8倍精度也無法窮盡所有實數(shù)只是精確度更高,適應(yīng)范圍更廣呛凶。那么精確度是怎么消失的呢男娄?我們通常說的實數(shù)都是十進(jìn)制的,JS引擎里用的也是十進(jìn)制的漾稀,但是存儲卻是二進(jìn)制模闲,但是二進(jìn)制在轉(zhuǎn)十進(jìn)制時存在很多缺陷,分兩種情況說:第一種是整數(shù)崭捍,正整數(shù)能精準(zhǔn)表示的范圍是0到Math.pow(2, 53)尸折,因為通過調(diào)節(jié)指數(shù)分?jǐn)?shù)都可以變成一一對應(yīng)的整數(shù),但是超過這個范圍時就存在問題了殷蛇,因為已經(jīng)到了分?jǐn)?shù)能一一對應(yīng)的最大值实夹,例如:Math.pow(2, 53)到Math.pow(2, 54)這個區(qū)間的數(shù)字分?jǐn)?shù)(二進(jìn)制)每增加1,比如從0到1的改變會相當(dāng)于十進(jìn)制里的2個數(shù)字粒梦,且是偶數(shù)亮航;Math.pow(2, 54)到Math.pow(2, 55)區(qū)間則是代表4個數(shù)字;依次類推指數(shù)增長匀们。然后真正的JS引擎顯示時卻并非一定準(zhǔn)確依賴這個規(guī)則缴淋。所以整數(shù)的精確度為小于Math.pow(2, 53),小于15位的十進(jìn)制整數(shù)是準(zhǔn)確的。之后越來越不準(zhǔn)確重抖,直到超過21位會用指數(shù)顯示露氮。小數(shù)精確度也存在丟失現(xiàn)象和整數(shù)不同的是平常用的小數(shù)都存在這種現(xiàn)象比如0.1,用分?jǐn)?shù)表示是1/10钟沛,在可以表示的所有數(shù)里最接近的是:是一個分?jǐn)?shù)位循環(huán)的分?jǐn)?shù)0.000110011001100...(1100循環(huán))畔规,所以只能用能表示的數(shù)里最接近0.1這個值得數(shù)表示,小數(shù)不準(zhǔn)確的原因是無法跟實數(shù)一一對應(yīng)讹剔,精確度大概是17位油讯。
補充知識點:
js并非一種數(shù)字類型還有其他幾種比如32位和16位以及整數(shù),處于對整數(shù)精確度的需求有些瀏覽器實現(xiàn)了精確的十進(jìn)制表示:biginteger延欠。
js有兩種表示法:固定數(shù)字表示和科學(xué)計數(shù)法表示陌兑,前者用于小數(shù)點后少于5個0或者長度小于21位,否則使用以10為基底的科學(xué)計數(shù)法由捎。