JavaScript 在數值的小數點與整數的處理上有著很多的細節,在操作過後才了解到不單純只是整數與小數等一些運算,其中也包涵著浮點數、進制方法處理的差別,先以了解的方式針了理解的地方記錄。


數值概念

整數和浮點數

JavaScript 整數與相關數值,預設 64 位浮點數形式儲存,1 與 1.0 是相同。

底層根本沒有整數,所有數字都是小數。

數值精度

64 二進制位最左邊開始。

  • 第 1 位:符號位,0 表示正數,1 表示負數
  • 第 2 位到第 12 位(共 11 位):指數部分
  • 第 13 位到第 64 位(共 52 位):小數部分(即有效數字)

符號位決定了一個數的正負,指數部分決定了數值的大小,小數部分決定了數值的精度。
指數部分的值在 0 到 2047 之間(不含兩個端點),效數字的第一位默認總是 1,不保存在 64 位浮點數之中。
64 位浮點數之中,最長可能為 52 位,效數字最長為 53 個二進制位。
大於 2 的 53 次方以後,整數運算的結果開始出現錯誤。所以,大於 2 的 53 次方的數值,都無法保持精度。對 15 位的十進制數都可以精確處理。

大於 2 的 53 次方以後,多出來的有效數字(最後三位的 111)都會無法保存,變成 0。


數值的表示法

數值有多種表示方法,35(十進制)和 0xFF(十六進制)
數值也可以採用科學計數法表示,下面是幾個科學計數法的例子。

科學計數法允許字母 e 或 E 的後面,跟著一個整數,表示這個數值的指數部分,兩種情況自動將數值轉為科學計數法表示,其他情況都採用字面形式直接表示。

小數點前的數字多於 21 位。

小數點後的零多於 5 個。


數值的進制

使用字面量 (literal) 直接表示一個數值時,對整數提供四種進制的表示方法:

  • 十進制:沒有前導0的數值。
  • 八進制:有前綴 0o0O 的數值,或者有前導 0、且只用到 0 – 7 的八個阿拉伯數字的數值。
  • 十六進制:有前綴 0x0X 的數值。
  • 二進制:有前綴 0b0B 的數值。

預設八進制、十六進制、二進制轉為十進制。

八進制、十六進制、二進制的數值裡面,出現不屬於該進制的數字,就會報錯。十六進制出現了字母 z、八進制出現數字 8、二進制出現數字 2,因此報錯。

有前導 0 的數值會被視為八進制,但是如果前導 0 後面有數字 89,則該數值被視為十進制。

前導 0 表示八進制,處理時很容易造成混亂。ES5 的嚴格模式和 ES6,已經廢除了這種表示法,但是瀏覽器為了兼容以前的代碼,目前還繼續支持這種表示法。


特殊數值

正零和負零

64 位浮點數之中,有一個二進制位是符號位。一個數都有一個對應的負值,就連 0 也分 +0-0,區別就是 64 位浮點數表示法的符號位不同但是等價。

+0-0 當作分母,返回的值是不相等的。

除以正零得到 +Infinity,除以負零得到 -Infinity,這兩者是不相等的。

NaN

NaN 非數字 (Not a Number) 將字符串解析成數字出錯時表示。

透過數值處理的方法也是,當不符合對應的設定,也會出現 NaN

0 除以 0 也會得到 NaN

NaN 是一個特殊數值屬於 Number

NaN 不等於任何值包括本身。

陣列中的 indexOf 方法是嚴格相等運算符,該方法對 NaNa 不成立。

NaN 在布林運算時被當作 false

NaN 與任何數(包括它自己)的運算,得到的都是 NaN


轉換方法

parseInt() 字串轉為整數與進制轉換

基本用法

將字串轉為整數

字串頭部有空格,空格會被自動去除

parseInt 的參數不是字串,則會先轉為字串再轉換。

字串轉整數時逐一將字符依次轉換,遇到不能轉為數字的字符就不再進行下去,將轉好的部分傳回出。

字串以 0 開頭,將其按照 10 進制解析。

會自動轉為科學計數法的數字,表示方法視為字串,因此導致一些奇怪的結果。

進制轉換

parseInt 第二個參數( 236 之間)解析的值的進制,預設是十進制處理,透過第二參數指定特定的進制數,二進制、六進制、八進制的 1000 可以用 parseInt 方法進行進制的轉換。。

二個參數不是數值,會被自動轉為一個整數,設定參數只有在 236 之間,設定超過會回應出 NaN

二個參數數值設定 0 會直接以十進位運算。

undefinednull 直接忽略。

二進制只針對第一行個數值以 01 處理,其他後面的位數都會視為沒有意義,如果直接操過 1 的數字回應 NaN

isNaN() 判斷非數字

用來判斷一個值是否為非數字 (Not a Number),由下例得知非數值會得到 true,而數值得到的是 false

isNaN 只對數值,傳入其他值會先轉成數值。 isNaNtrue 的值可能不是 NaN,而是一個字串。

物件和陣列 isNaN 也傳回 true

但在陣列要特別注意,其中裡面還有的值,值是字串數字或是純數值,就會回傳出來的是 false,陣列能被 Number 函式轉成數值再向 isNaN 處理。

isFinite() 值是否為正常的數值

isFinite 方法傳回一個布林值,表示某個值是否為正常的數值,以數值來說一定會得到的是 true,特別注意 null 所得到的也是 true


判斷正數還是負數

以 0 數值以 if else 做為判斷

Math.sign(x) 函數返回一個數字的符號,指示數字是正數,負數還是零。

signMath 的一個靜態方法,使用 Math.sign()
5 種返回值:

  • 1 (正數)
  • -1 (負數)
  • 0 (正零)
  • -0 (負零)
  • NaN (非數值)


參考資料