[TOC]
# **Number數值類型**
**表示方式**
  JavaScript 中的數字類型只有 Number 一種,Number 類型采用 IEEE754 標準中的 “雙精度浮點數” 來表示一個數字,不區分整數和浮點數 。
<br>
## **1、存儲結構**
  在 IEEE754 中,雙精度浮點數采用 64 位存儲,即 8 個字節表示一個浮點數 。其存儲結構如下圖所示:

<br>
  指數位可以通過下面的方法轉換為使用的指數值:

<br>
## **2 、數值范圍**
  從存儲結構中可以看出, 指數部分的長度是11個二進制,即指數部分能表示的最大值是 2047(211\-1),取中間值進行偏移,用來表示負指數,也就是說指數的范圍是 \[-1023,1024\] 。因此,這種存儲結構能夠表示的數值范圍為 21024?到 2\-1023?,超出這個范圍的數無法表示 。21024?和 2\-1023??轉換為科學計數法如下所示:
>[success]1.7976931348623157 × 10308
>
>5 × 10\-324
  因此,JavaScript 中能表示的最大值是?**1.7976931348623157?× 10308**,最小值為?**5 × 10\-324**。
這兩個邊界值可以分別通過訪問 Number 對象的 MAX\_VALUE 屬性和 MIN\_VALUE 屬性來獲取:
>[success]Number.MAX_VALUE;// 1.7976931348623157e+308
> Number.MIN_VALUE;// 5e-324
  如果數字超過最大值或最小值,JavaScript 將返回一個不正確的值,這稱為 “**正向溢出(overflow)**” 或 “**負向溢出(underflow)**” 。?
>[success]12345Number.MAX_VALUE+1 == Number.MAX_VALUE;//trueNumber.MAX_VALUE+1e292;//InfinityNumber.MIN_VALUE + 1;//1Number.MIN_VALUE - 3e-324;//0Number.MIN_VALUE - 2e-324;//5e-324
<br>
## **3、 數值精度**
  在 64 位的二進制中,符號位決定了一個數的正負,指數部分決定了數值的大小,小數部分決定了數值的精度。
  IEEE754 規定,有效數字第一位默認總是1 。因此,在表示精度的位數前面,還存在一個 “隱藏位”?,固定為 1 ,但它不保存在 64 位浮點數之中。也就是說,有效數字總是 1.xx...xx 的形式,其中 xx..xx 的部分保存在 64 位浮點數之中,最長為52位 。所以,JavaScript 提供的有效數字最長為 53 個二進制位,其內部實際的表現形式為:
>[success](-1)^符號位 \* 1.xx...xx \* 2^指數位
  這意味著,JavaScript 能表示并進行精確算術運算的整數范圍為:\[-253\-1,253\-1\],即從最小值 -9007199254740991 到最大值 9007199254740991 之間的范圍 。
```
Math.pow(2, 53)-1 ;// 9007199254740991
-Math.pow(2, 53)-1 ;// -9007199254740991
```
可以通過 Number.MAX\_SAFE\_INTEGER 和??Number.MIN\_SAFE\_INTEGER 來分別獲取這個最大值和最小值。?
```
console.log(Number.MAX_SAFE_INTEGER) ;// 9007199254740991
console.log(Number.MIN_SAFE_INTEGER) ;// -9007199254740991
```
對于超過這個范圍的整數,JavaScript 依舊可以進行運算,但卻不保證運算結果的精度。
```
Math.pow(2, 53) ;// 9007199254740992
Math.pow(2, 53) + 1;//9007199254740992
9007199254740993;//9007199254740992
90071992547409921;//90071992547409920
0.923456789012345678;//0.9234567890123456
```
<br>
## **4、 精度丟失**
  計算機中的數字都是以二進制存儲的,如果要計算 0.1 + 0.2 的結果,計算機會先把 0.1 和 0.2 分別轉化成二進制,然后相加,最后再把相加得到的結果轉為十進制 。
  但有一些浮點數在轉化為二進制時,會出現無限循環 。比如, 十進制的 0.1 轉化為二進制,會得到如下結果:
>[success] 0.0001 1001 1001 1001 1001 1001 1001 1001 …(1001無限循環)
  而存儲結構中的尾數部分最多只能表示 53 位。為了能表示 0.1,只能模仿十進制進行四舍五入了,但二進制只有 0 和 1 , 于是變為 0 舍 1 入 。 因此,0.1 在計算機里的二進制表示形式如下:
>[success] 0.0001100110011001100110011001100110011001100110011001101
  用標準計數法表示如下:
>[success] (?1)0?×?2?4×?(1.1001100110011001100110011001100110011001100110011010)2
  同樣,0.2 的二進制也可以表示為:?
>[success] (?1)0?×?2?3?×?(1.1001100110011001100110011001100110011001100110011010)2?
  在計算浮點數相加時,需要先進行?“對位”,將較小的指數化為較大的指數,并將小數部分相應右移:
>[success] 0.1→?(?1)0?×?2?3?×?(0.11001100110011001100110011001100110011001100110011010)2
> 0.2→?(?1)0?×?2?3?×?(1.1001100110011001100110011001100110011001100110011010)2
  最終,“0.1 + 0.2” 在計算機里的計算過程如下:

  經過上面的計算過程,0.1 + 0.2 得到的結果也可以表示為:
>[success] (?1)0?×?2?2?×?(1.0011001100110011001100110011001100110011001100110100)2
  然后,通過 JS 將這個二進制結果轉化為十進制表示:
>[success] 12(-1)**0 * 2**-2 * (0b10011001100110011001100110011001100110011001100110100 * 2**-52);//0.30000000000000004console.log(0.1 + 0.2) ;// 0.30000000000000004
  這是一個典型的精度丟失案例,從上面的計算過程可以看出,0.1 和 0.2 在轉換為二進制時就發生了一次精度丟失,而對于計算后的二進制又有一次精度丟失 。因此,得到的結果是不準確的。
<br>
## **5、 特殊數值**
JavaScript 提供了幾個特殊數值,用于判斷數字的邊界和其他特性 。如下所示:
* Number.MAX\_VALUE:JavaScript 中的最大值
* Number.MIN\_VALUE:JavaScript 中的最小值
* Number.MAX\_SAFE\_INTEGER:最大安全整數,為 253\-1
* Number.MIN\_SAFE\_INTEGER:最小安全整數,為 -(253\-1)
* Number.POSITIVE\_INFINITY:對應 Infinity,代表正無窮
* Number.NEGATIVE\_INFINITY:對應 -Infinity,代表負無窮
* Number.EPSILON:是一個極小的值,用于檢測計算結果是否在誤差范圍內
* Number.NaN:表示非數字,NaN與任何值都不相等,包括NaN本身
* Infinity:表示無窮大,分 正無窮 Infinity 和 負無窮 -Infinity
<br>
## **6 、數值轉換**
有 3 個函數可以把非數值轉換為數值,分別如下:
```
Number(value)
parseInt(string [, radix])
parseFloat(string)
```
  Number() 可以用于任何數據類型,而另兩個函數則專門用于把字符串轉換成數值。
  對于字符串而言,Number() 只能對字符串進行整體轉換,而 parseInt() 和 parseFloat() 可以對字符串進行部分轉換,即只轉換第一個無效字符之前的字符。
對于不同數據類型的轉換,Number() 的處理也不盡相同,其轉換規則如下:
【1】如果是 Boolean 值,true 和 false 將分別被轉換為 1 和 0。?
【2】如果是數字值,只是簡單的傳入和返回。
【3】如果是 null 值,返回 0。
【4】如果是 undefined,返回 NaN。
【5】如果是字符串,遵循下列規則:
* 如果字符串中只包含數字(包括前面帶正號或負號的情況),則將其轉換為十進制數值;?
* 如果字符串中包含有效的浮點格式,則將其轉換為對應的浮點數值;?
* 如果字符串中包含有效的十六進制格式,則將其轉換為相同大小的十進制整數值;?
* 如果字符串是空的(不包含任何字符),則將其轉換為 0;?
* 如果字符串中包含除上述格式之外的字符,則將其轉換為 NaN。
【6】如果是對象,則調用對象的 valueOf() 方法,然后依照前面的規則轉換返回的值。如果轉換的結果是 NaN,則調用對象的 toString()?方法,然后再次依照前面的規則轉換返回的字符串值。
需要注意的是:
>[success]一元加操作符加號 “+” 和 Number() 具有同樣的作用。
  在 ECMAScript 2015 規范中,為了實現全局模塊化,Number 對象重寫了 parseInt 和 parseFloat 方法,但和對應的全局方法并無區別。
12Number.parseInt === parseInt;// trueNumber.parseFloat === parseFloat;// true
<br>
## **7 、位運算**
  位運算作用于最基本的層次上,即按內存中表示數值的位來操作數值。ECMAScript 中的數值以64位雙精度浮點數存儲,但位運算只能作用于整數,因此要先將 64 位的浮點數轉換成 32 位的整數,然后再進行位運算,最后再將計算結果轉換成64位浮點數存儲。常見的位運算有以下幾種:
* 按位非(NOT):~?
* 按位與(AND):&?
* 按位或(OR): |
* 按位異或(XOR):^
* 左移:<<
* 有符號右移:>>?
* 無符號右移:>>>
需要注意的是:
>[success] “有符號右移” 和 “無符號右移” 只在計算負數的情況下存在差異,>> 在符號位的右側補0,不移動符號位;而 >>> 是在符號位的左側補0,符號位發生移動和改變。
<br>
## **8、 四舍五入**
  JavaScript 對數字進行四舍五入操作的 API 有 ceil,floor,round,toFixed,toPrecision 等,詳細介紹請參考:[JavaScript 中的四舍五入] http://www.cnblogs.com/onepixel/p/5141566.html