JS 的整型你懂了嗎?

JS 中的最大安全整數是多少?

JS 中全部的數字類型,實際存儲都是經過 8 字節 double 浮點型 表示的。浮點數並非可以精確表示範圍內的全部數的, 雖然 double 浮點型的範圍看上去很大: 2.23x10^(-308) ~ 1.79x10^308。 能夠表示的最大整數能夠很大,但可以精確表示,使用算數運算的並無這麼大。javascript

它其實連這樣的簡單加法也會算錯:html

console.log(0.1 + 0.2)
//output: 0.30000000000000004

因此在 js 中可以安全使用的有符號 安全 大整數(注意這裏是指可以安全使用,進行算數運算的範圍),並不像其餘語言在 64 位環境中那樣是:java

2^63 - 1;//9223372036854775807

而是node

Math.pow(2, 53) - 1     // 9007199254740991

JS 的最大和最小安全值能夠這樣得到:git

console.log(Number.MAX_SAFE_INTEGER); //9007199254740991
console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991

經過下面的例子,你會明白爲何大於這個值的運算是不安全的:github

var x = 9223372036854775807;
console.log(x === x + 1);// output: true
console.log(9223372036854775807 + 1000); //output: 9223372036854776000

這些運算都是錯誤的結果, 由於它們進行的都是浮點數運算會丟失精度。sql

爲何是這個值?

double 浮點數結構以下:數據庫

圖片描述

  • 1 位符號位
  • 11 位指數位
  • 52 位尾數位

使用 52 位表示一個數的整數部分,那麼最大能夠精確表示的數應該是 2^52 - 1 纔對, 就像 64 位表示整數時那樣: 2^63 - 1 (去掉 1 位符號位)。 但其實浮點數在保存數字的時候作了規格化處理,以 10 進製爲例:後端

20*10^2 => 2*10^3 //小數點前只須要保留 1 位數

對於二進制來講, 小數點前保留一位, 規格化後始終是 1.***, 節省了 1 bit,這個 1 並不須要保存。安全

如何處理大整數

Nodejs 愈來愈多的應用到後端的開發中, 不可避免的須要處理這樣的溢出問題, 好在已經有不少優秀的第三方庫來解決該問題:bignumbigint

大整數與數據庫

Mysql 能處理的各個整形範圍以下

//每種類型的第二行爲無符號範圍
TYPE         BYTE   MIN            MAX
TINYINT      1     -128            127
                                   255
SMALLINT     2    -32768          32767
                                  65535
MEDIUMINT    3    -8388608       8388607
                                 16777215
INT          4   -2147483648    2147483647
                                4294967295
BIGINT       8  -9223372036854775808    9223372036854775807
                                       18446744073709551615

BIGINT 就是 64 位整數, 一旦要處理的數據量超過了 BIGINT 能存儲的範圍,便要考慮使用字符串保存, 壞處是數字的算數運算須要經過應用程序使用大整數庫來處理,不能依賴於數據庫。

注: 經常看到 BIGINT(5) 或者 INT(10), 括號裏的 5 或 10 只是表示展現寬度,並不影響數的精度範圍和存儲字節數,須要與 VARCHAR(100)或 DECIMAL(10,2)區分開

如何處理要求精度的運算?

當涉及財物類型的運算時, 位數通常不會溢出, 但精度要求回更高。數據庫保存這些值時,須要使用 DECIMAL (NUMERIC 類型與之相同) 類型保存字段, 防止精度丟失。

當心位移操做

前面討論了可使用的安全整數範圍,但在作位移操做時請當心:位移操做時,會將整數截斷爲 32 位有符號整型。也就是說超出這個範圍的位移操做將會獲得錯誤的值。例如:

196 << 24;// 輸出: -1006632960 正確應爲: 3288334336

位移的一些技巧能夠戳 -> 這裏

延伸閱讀

代碼之謎(四)- 浮點數(從驚訝到思考)

若是你有更好的關於浮點數相關學習資料, 但願能留言推薦!

相關文章
相關標籤/搜索