Giá trị số nguyên cao nhất của JavaScript mà một số có thể đạt được mà không mất độ chính xác là gì?


951

Điều này được xác định bởi ngôn ngữ? Có tối đa xác định? Có khác nhau trong các trình duyệt khác nhau?


5
Bạn không cần phụ thuộc vào giới hạn của JS với các thư viện như github.com/MikeMcl/big.js , xem ví dụ ở đây để kiểm tra độ tin cậy của nó
Dmitri Zaitsev

2
giá trị số nguyên cao nhất bạn có thể sử dụng với big.js là bao nhiêu?
George

@George Đây là API big.js: mikemcl.github.io/big.js/#dp
simhumileco

Câu hỏi không có ý nghĩa. Điều đó có nghĩa là một số "đi đến" một giá trị nguyên? Nếu bạn chỉ muốn hỏi số nguyên cao nhất bạn có thể đại diện trong JS là gì, thì Số cao nhất (hữu hạn) là một số nguyên.
Veky

@DmitriZaitsev Chúng tôi không cần phải phụ thuộc vào các thư viện bên ngoài nữa (ít nhất là trên một số trình duyệt). 1n << 10000nlà một số nguyên thực sự rất lớn, không mất bất kỳ độ chính xác nào, không yêu cầu bất kỳ sự phụ thuộc nào (và không cần phải nói, thậm chí không gần với giới hạn).
Amadan

Câu trả lời:


868

JavaScript có hai loại số: NumberBigInt.

Loại số được sử dụng thường xuyên nhất Number, là số IEEE 754 có dấu phẩy động 64 bit .

Giá trị tích phân chính xác lớn nhất của loại này Number.MAX_SAFE_INTEGERlà:

  • 2 53 -1, hoặc
  • +/- 9,007,199,254,740,991 hoặc
  • chín triệu một nghìn bảy nghìn một trăm chín mươi chín tỷ hai trăm năm mươi bốn triệu bảy trăm bốn mươi nghìn chín trăm chín mươi mốt

Để đặt điều này trong phối cảnh: một triệu triệu byte là một petabyte (hoặc một nghìn terabyte).

"An toàn" trong ngữ cảnh này đề cập đến khả năng thể hiện chính xác các số nguyên và so sánh chính xác chúng.

Từ thông số kỹ thuật:

Lưu ý rằng tất cả các số nguyên dương và âm có độ lớn không lớn hơn 2 53 đều có thể biểu diễn trong Numberloại (thực tế, số nguyên 0 có hai biểu diễn, +0 và -0).

Để sử dụng một cách an toàn các số nguyên lớn hơn số này, bạn cần sử dụng BigInt, không có giới hạn trên.

Lưu ý rằng các toán tử bit và toán tử dịch chuyển hoạt động trên các số nguyên 32 bit, do đó, trong trường hợp đó, số nguyên an toàn tối đa là 2 31 -1, hoặc 2.147.483.647.

const log = console.log
var x = 9007199254740992
var y = -x
log(x == x + 1) // true !
log(y == y - 1) // also true !

// Arithmetic operators work, but bitwise/shifts only operate on int32:
log(x / 2)      // 4503599627370496
log(x >> 1)     // 0
log(x | 1)      // 1


Lưu ý kỹ thuật về chủ đề của số 9,007,199,254,740,992: Có một đại diện chính xác của IEEE-754 của giá trị này và bạn có thể gán và đọc giá trị này từ một biến, vì vậy, đối với các ứng dụng được chọn rất cẩn thận trong miền số nguyên nhỏ hơn hoặc bằng giá trị này, bạn có thể coi đây là giá trị tối đa.

Trong trường hợp chung, bạn phải coi giá trị IEEE-754 này là không chính xác, vì không rõ liệu nó có mã hóa giá trị logic 9,007,199,254,740,992 hay 9,007,199,254,740,993.


75
Điều này có vẻ đúng, nhưng có nơi nào đó được xác định, đây là MAX_INT hoặc Integer của Java.MAX_VALUE?
TALlama

48
4294967295 === Math.pow(2,32) - 1;
CoolAJ86

13
Vậy số nguyên nhỏ nhất và lớn nhất chúng ta có thể sử dụng để đảm bảo độ chính xác chính xác là gì?
Pacerier

38
Có lẽ đáng lưu ý rằng không có (int) thực tế trong javascript. Mỗi phiên bản của Number là (float) hoặc NaN.
Củ cải đường-Củ cải đường

53
9007199254740992 không thực sự là giá trị tối đa, bit cuối cùng ở đây đã được coi là 0 và do đó bạn đã mất 1 bit chính xác. Số an toàn thực sự là 9007199254740991 (Số.MAX_SAFE_INTEGER)
Willem D'Haeseleer

461

> = ES6:

Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;

<= ES5

Từ tài liệu tham khảo :

Number.MAX_VALUE;
Number.MIN_VALUE;


23
Tôi đã chỉnh sửa câu hỏi để chính xác hơn một chút về việc muốn các giá trị Số nguyên tối đa, không chỉ giá trị Số tối đa. Xin lỗi vì sự nhầm lẫn, ở đây.
TALlama

5
Kết quả trả về có được đảm bảo bằng nhau trên tất cả các trình duyệt không?
Pacerier

7
Lưu ý rằng đó Number.MIN_VALUElà số dương nhỏ nhất có thể . Các ít nhất giá trị (tức là ít hơn bất cứ điều gì khác) có lẽ là -Number.MAX_VALUE.
Michael Scheper

34
ES6 giới thiệu Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER
superlukas

2
Vì vậy, trong trường hợp này, chúng ta nên bỏ phiếu trả lời vì nó sai cho câu hỏi cập nhật, hoặc bỏ nó vì Peter Baily đã đúng vào thời điểm nó được trả lời?
rocketsarefast

112

Đó là 2 53 == 9 007 199 254 740 992. Điều này là doNumber s được lưu dưới dạng dấu phẩy động trong lớp phủ 52 bit.

Giá trị tối thiểu là -2 53 .

Điều này làm cho một số điều thú vị xảy ra

Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true

Và cũng có thể nguy hiểm :)

var MAX_INT = Math.pow(2, 53); // 9 007 199 254 740 992
for (var i = MAX_INT; i < MAX_INT + 2; ++i) {
    // infinite loop
}

Đọc thêm: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html


1
mặc dù người ta sẽ không bao giờ đi đến cuối vòng lặp đó trong khung thời gian lành mạnh, bạn có thể muốn nóii += 1000000000
ninjagecko

2
@ninjagecko, anh ấy bắt đầu ở MAX_INT nên kết thúc ở ngay đó. Ngoài ra, sử dụng i + = 1000000000 sẽ khiến nó không còn là một vòng lặp vô hạn. Thử nó.
Ted Bigham

@TedBigham: Ah oops, đã sẵn sàng quá nhanh qua đó. Cảm ơn đã sửa tôi hai lần.
ninjagecko

Xem đối số của Jimmy cho 9,007,199,254,740,991 thay vì 9,007,199,254,740,992 tại đây . Điều đó, kết hợp với theo dõi của tôi, có vẻ thuyết phục.
TJ Crowder

60

Trong JavaScript, có một số được gọi là Infinity.

Ví dụ:

(Infinity>100)
=> true

// Also worth noting
Infinity - 1 == Infinity
=> true

Math.pow(2,1024) === Infinity
=> true

Điều này có thể đủ cho một số câu hỏi liên quan đến chủ đề này.


25
Một cái gì đó cho tôi biết vô hạn không đủ điều kiện như một số nguyên. :)
devios1

7
Nhưng nó đủ tốt để khởi tạo một minbiến khi bạn đang tìm kiếm một giá trị tối thiểu.
djjeck

9
Lưu ý rằngInfinity - 1 === Infinity
H.Wolper

2
cũng (Infinity <100) => false và Math.pow (2.1024) === Infinity
Sijav

6
Cũng không có giá trị gì mà nó cũng xử lý Infinity tiêu cực. Vì vậy1 - Infinity === -Infinity
dmccabe

41

Câu trả lời của Jimmy thể hiện chính xác phổ số nguyên JavaScript liên tục là -9007199254740992 đến 9007199254740992 (xin lỗi 9007199254740993, bạn có thể nghĩ rằng mình là 9007199254740993, nhưng bạn đã nhầm! Trình diễn bên dưới hoặc trong jsfiddle ).

console.log(9007199254740993);

Tuy nhiên, không có câu trả lời nào tìm thấy / chứng minh điều này theo chương trình (ngoài câu hỏi CoolAJ86 được ám chỉ trong câu trả lời của anh ta sẽ kết thúc sau 28,56 năm;), vì vậy đây là cách hiệu quả hơn một chút (chính xác hơn, nó hiệu quả hơn vào khoảng 28.559999999968312 năm :), cùng với một câu đố thử nghiệm :

/**
 * Checks if adding/subtracting one to/from a number yields the correct result.
 *
 * @param number The number to test
 * @return true if you can add/subtract 1, false otherwise.
 */
var canAddSubtractOneFromNumber = function(number) {
    var numMinusOne = number - 1;
    var numPlusOne = number + 1;
    
    return ((number - numMinusOne) === 1) && ((number - numPlusOne) === -1);
}

//Find the highest number
var highestNumber = 3; //Start with an integer 1 or higher

//Get a number higher than the valid integer range
while (canAddSubtractOneFromNumber(highestNumber)) {
    highestNumber *= 2;
}

//Find the lowest number you can't add/subtract 1 from
var numToSubtract = highestNumber / 4;
while (numToSubtract >= 1) {
    while (!canAddSubtractOneFromNumber(highestNumber - numToSubtract)) {
        highestNumber = highestNumber - numToSubtract;
    }
    
    numToSubtract /= 2;
}        

//And there was much rejoicing.  Yay.    
console.log('HighestNumber = ' + highestNumber);


8
@ CoolAJ86: Lol, tôi đang mong chờ đến ngày 15 tháng 3 năm 2040. Nếu số của chúng tôi
trùng

var x = Math.pow (2,53) -3; while (x! = x + 1) x ++; -> 9007199254740991
MickLH

@MickLH: Tôi nhận được 9007199254740992 với mã đó . Bạn đang sử dụng công cụ JavaScript nào để kiểm tra?
Briguy37

Bạn nhận được 9007199254740992 với mã của riêng bạn, tôi đã không sử dụng giá trị cuối cùng của x, nhưng sự lảng tránh cuối cùng của x ++ vì lý do hoang tưởng. Google Chrome btw.
MickLH

@MickLH: việc đánh giá x++cung cấp cho bạn giá trị của x trước khi gia tăng xảy ra, do đó có thể giải thích sự khác biệt. Nếu bạn muốn biểu thức ước tính giống với giá trị cuối cùng của x, bạn nên thay đổi nó thành ++x.
peterflynn

32

Để được an toàn

var MAX_INT = 4294967295;

Lý luận

Tôi nghĩ tôi sẽ thông minh và tìm ra giá trị x + 1 === x theo cách tiếp cận thực tế hơn.

Máy của tôi chỉ có thể đếm 10 triệu mỗi giây hoặc lâu hơn ... vì vậy tôi sẽ đăng lại với câu trả lời dứt khoát trong 28,56 năm.

Nếu bạn không thể đợi lâu như vậy, tôi sẵn sàng đặt cược rằng

  • Hầu hết các vòng lặp của bạn không chạy trong 28,56 năm
  • 9007199254740992 === Math.pow(2, 53) + 1 là đủ bằng chứng
  • Bạn nên tuân theo 4294967295đó là Math.pow(2,32) - 1để tránh các vấn đề dự kiến ​​với dịch chuyển bit

Tìm kiếm x + 1 === x:

(function () {
  "use strict";

  var x = 0
    , start = new Date().valueOf()
    ;

  while (x + 1 != x) {
    if (!(x % 10000000)) {
      console.log(x);
    }

    x += 1
  }

  console.log(x, new Date().valueOf() - start);
}());

4
Bạn không thể bắt đầu nó lúc 2 ^ 53 - 2 để kiểm tra? (có bạn có thể, tôi chỉ cố gắng nó, ngay cả với -3 đến được an toàn: var x = Math.pow (2,53) -3; while (x = x + 1) x ++;) -> 9007199254740991
MickLH

Câu trả lời tốt đẹp! Hơn nữa, tôi biết giá trị được giải quyết, nhưng tại sao không sử dụng tìm kiếm nhị phân cho tìm kiếm của nó?
higuaro

1
Có gì vui trong đó? Bên cạnh đó, @ Briguy37 đánh bại tôi: stackoverflow.com/a/11639421/151312
CoolAJ86

lưu ý rằng MAX_INT 'an toàn' dựa trên 32 bit này sẽ không hoạt động khi so sánh với các giá trị Ngày. 4294967295 là như vậy ngày hôm qua!
Jerry

1
Câu trả lời "Để được an toàn: var MAX_INT = 4294967295;" không hài hước Nếu bạn không bẻ khóa, đừng lo lắng về điều đó (trừ khi bạn cần một int lớn hơn 4294967295, trong trường hợp đó bạn có thể nên lưu trữ nó dưới dạng chuỗi và sử dụng thư viện bigint).
CoolAJ86

29

Câu trả lời ngắn gọn là tùy nó.

Nếu bạn đang sử dụng toán tử bitwise ở bất cứ đâu (hoặc nếu bạn đang đề cập đến độ dài của Mảng), thì các phạm vi là:

Chưa ký: 0…(-1>>>0)

Đã ký: (-(-1>>>1)-1)…(-1>>>1)

(Điều đó xảy ra khi các toán tử bitwise và độ dài tối đa của một mảng bị giới hạn ở các số nguyên 32 bit.)

Nếu bạn không sử dụng toán tử bitwise hoặc làm việc với độ dài mảng:

Đã ký: (-Math.pow(2,53))…(+Math.pow(2,53))

Những hạn chế này được áp đặt bởi biểu diễn bên trong của loại Số Số, thường tương ứng với biểu diễn dấu phẩy động có độ chính xác kép của IEEE 754. (Lưu ý rằng không giống như các số nguyên được ký điển hình, độ lớn của giới hạn âm giống như độ lớn của giới hạn dương, do các đặc điểm của biểu diễn bên trong, thực sự bao gồm 0 âm !)


Đây là câu trả lời tôi muốn tìm hiểu về cách chuyển đổi X thành số nguyên 32 bit hoặc số nguyên không dấu. Nâng cao câu trả lời của bạn cho điều đó.
Charlie Affumigato

29

Bản thảo 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;

1
Coi chừng đây không phải (chưa) được hỗ trợ bởi tất cả các trình duyệt! Ngày nay iOS (thậm chí không có chrome), Safari và IE không thích nó.
cregox

5
Vui lòng đọc kỹ câu trả lời, chúng tôi không sử dụng triển khai mặc định của Number.MAX_SAFE_INTEGER trong ECMAScript 6, chúng tôi đang xác định nó bằng Math.pow (2, 53) -1
WaiKit Kung

Tôi nghĩ rằng nó chỉ là một tài liệu tham khảo về cách nó được thực hiện trong ECMA 6! : PI nghĩ rằng bình luận của tôi vẫn còn hiệu lực. Tất cả một vấn đề của bối cảnh. ;)
cregox

3
Có đáng tin cậy để tính toán MAX_SAFE_INTEGERtrong tất cả các trình duyệt bằng cách làm việc ngược? Thay vào đó bạn nên di chuyển về phía trước? Tức là, Số.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) + 1;
kjv

Math.pow(2, 53)-1một hoạt động an toàn? Nó đi một lớn hơn số nguyên an toàn lớn nhất.
ioquatix

21

Nhiều câu trả lời từ thời gian trước đã cho thấy kết quả truecủa 9007199254740992 === 9007199254740992 + 1việc xác minh rằng 9 007 199 254 740 991 là số nguyên tối đa và an toàn.

Điều gì xảy ra nếu chúng ta tiếp tục tích lũy:

input: 9007199254740992 + 1  output: 9007199254740992  // expected: 9007199254740993
input: 9007199254740992 + 2  output: 9007199254740994  // expected: 9007199254740994
input: 9007199254740992 + 3  output: 9007199254740996  // expected: 9007199254740995
input: 9007199254740992 + 4  output: 9007199254740996  // expected: 9007199254740996

Chúng ta có thể tìm ra rằng trong số các số lớn hơn 9 007 199 254 740 992 , chỉ các số chẵn là có thể biểu diễn .

Đây là một lối vào để giải thích cách thức định dạng nhị phân 64 bit chính xác kép hoạt động trên này. Hãy xem 9 007 199 254 740 992 được tổ chức (đại diện) bằng cách sử dụng định dạng nhị phân này.

Sử dụng một phiên bản ngắn gọn để trình diễn nó từ 4 503 599 627 370 496 :

  1 . 0000 ---- 0000  *  2^52            =>  1  0000 ---- 0000.  
     |-- 52 bits --|    |exponent part|        |-- 52 bits --|

Ở bên trái của mũi tên, chúng ta có giá trị bit 1 và một điểm cơ số liền kề , sau đó bằng cách nhân 2^52, chúng ta phải di chuyển điểm cơ số 52 bước và đi đến cuối. Bây giờ chúng tôi nhận được 4503599627370496 trong nhị phân.

Bây giờ chúng ta bắt đầu tích lũy 1 đến giá trị này cho đến khi tất cả các bit được đặt thành 1, bằng 9 007 199 254 740 991 theo số thập phân.

  1 . 0000 ---- 0000  *  2^52  =>  1  0000 ---- 0000.  
                       (+1)
  1 . 0000 ---- 0001  *  2^52  =>  1  0000 ---- 0001.  
                       (+1)
  1 . 0000 ---- 0010  *  2^52  =>  1  0000 ---- 0010.  
                       (+1)
                        . 
                        .
                        .
  1 . 1111 ---- 1111  *  2^52  =>  1  1111 ---- 1111. 

Bây giờ, vì ở định dạng nhị phân 64 bit có độ chính xác kép , nó hoàn toàn phân bổ 52 bit cho phân số, không còn bit nào để mang thêm 1, vì vậy, điều chúng ta có thể làm là đặt tất cả các bit về 0 và Thao tác phần số mũ:

  |--> This bit is implicit and persistent.
  |        
  1 . 1111 ---- 1111  *  2^52      =>  1  1111 ---- 1111. 
     |-- 52 bits --|                     |-- 52 bits --|

                          (+1)
                                     (radix point has no way to go)
  1 . 0000 ---- 0000  *  2^52 * 2  =>  1  0000 ---- 0000. * 2  
     |-- 52 bits --|                     |-- 52 bits --|

  =>  1 . 0000 ---- 0000  *  2^53 
         |-- 52 bits --| 

Bây giờ chúng ta nhận được 9 007 199 254 740 992 và với số lượng lớn hơn nó, định dạng có thể giữ bằng 2 lần phân số , có nghĩa là bây giờ cứ 1 phần bổ sung trên phần phân số thực sự bằng 2 phần bổ sung, đó là lý do tại sao tăng gấp đôi -định dạng định dạng nhị phân 64 bit không thể giữ các số lẻ khi số lớn hơn 9 007 199 254 740 992 :

                            (consume 2^52 to move radix point to the end)
  1 . 0000 ---- 0001  *  2^53  =>  1  0000 ---- 0001.  *  2
     |-- 52 bits --|                 |-- 52 bits --|

Vì vậy, khi số lượng lớn hơn 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, chỉ có thể giữ 4 lần phân số :

input: 18014398509481984 + 1  output: 18014398509481984  // expected: 18014398509481985
input: 18014398509481984 + 2  output: 18014398509481984  // expected: 18014398509481986
input: 18014398509481984 + 3  output: 18014398509481984  // expected: 18014398509481987
input: 18014398509481984 + 4  output: 18014398509481988  // expected: 18014398509481988

Làm thế nào về số giữa [ 2 251 799 813 685 248 , 4 503 599 627 370 496 )?

 1 . 0000 ---- 0001  *  2^51  =>  1 0000 ---- 000.1
     |-- 52 bits --|                |-- 52 bits  --|

Giá trị bit 1 sau điểm cơ số chính xác là 2 ^ -1. (= 1/2, = 0,5) Vì vậy, khi số nhỏ hơn 4 503 599 627 370 496 (2 ^ 52), có một bit có sẵn để biểu thị 1/2 lần của số nguyên :

input: 4503599627370495.5   output: 4503599627370495.5  
input: 4503599627370495.75  output: 4503599627370495.5  

Ít hơn 2 251 799 813 685 248 (2 ^ 51)

input: 2251799813685246.75   output: 2251799813685246.8  // expected: 2251799813685246.75 
input: 2251799813685246.25   output: 2251799813685246.2  // expected: 2251799813685246.25 
input: 2251799813685246.5    output: 2251799813685246.5

// If the digits exceed 17, JavaScript round it to print it.
//, but the value is held correctly:

input: 2251799813685246.25.toString(2) 
output: "111111111111111111111111111111111111111111111111110.01"
input: 2251799813685246.75.toString(2) 
output: "111111111111111111111111111111111111111111111111110.11"
input: 2251799813685246.78.toString(2)   
output: "111111111111111111111111111111111111111111111111110.11"

Và phạm vi có sẵn của phần số mũ là gì? định dạng phân bổ 11 bit cho nó. Định dạng hoàn chỉnh từ Wiki : (Để biết thêm chi tiết xin vui lòng đến đó)

Định dạng điểm nổi kép của IEEE 754.svg

nhập mô tả hình ảnh ở đây

Vì vậy, để làm cho phần số mũ là 2 ^ 52, chúng ta chính xác cần đặt e = 1075.


13

Những người khác có thể đã đưa ra câu trả lời chung chung, nhưng tôi nghĩ rằng đó là một ý tưởng tốt để đưa ra một cách nhanh chóng để xác định nó:

for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);

Cung cấp cho tôi 9007199254740992 trong vòng chưa đến một phần nghìn giây trong Chrome 30.

Nó sẽ kiểm tra sức mạnh của 2 để tìm ra cái nào, khi 'thêm' 1, bằng chính mình.


Nó có thể làm hỏng ứng dụng của bạn, nghĩ.
Sapphire_Brick

8

Bất cứ điều gì bạn muốn sử dụng cho các hoạt động bitwise phải nằm trong khoảng 0x80000000 (-2147483648 hoặc -2 ^ 31) và 0x7fffffff (2147483647 hoặc 2 ^ 31 - 1).

Bảng điều khiển sẽ cho bạn biết rằng 0x80000000 bằng +2147483648, nhưng 0x80000000 & 0x80000000 bằng -2147483648.


6

Thử:

maxInt = -1 >>> 1

Trong Firefox 3.6, đó là 2 ^ 31 - 1.


2
@danorton: Tôi không chắc bạn hiểu bạn đang làm gì. ^có nghĩa là nâng lên sức mạnh . Trong bảng điều khiển javascript, ^XOR , không được nâng lên
kumarharsh

2
mở bảng điều khiển Chrome / Firefox. Loại 5 ^ 2. Trong nhị phân, 5 là 101và 2 là 010. Bây giờ, nếu bạn Bitwise XOR chúng, bạn sẽ 5(101) ^ 2(010) = 7(111) ĐỌC NÀY NẾU BẠNMath.pow()^
ĐÃ XÁC NHẬN

3
Một lần nữa, tôi hoàn toàn không bối rối. Tôi đã bình luận và đánh giá thấp những gì được viết . Nếu Math.pow () là những gì có nghĩa, thì đó là những gì nên được viết. Trong câu trả lời cho câu hỏi về JavaScript, việc sử dụng cú pháp của một ngôn ngữ khác là không phù hợp. Thậm chí còn không phù hợp hơn khi sử dụng cú pháp hợp lệ trong JavaScript, nhưng với cách diễn giải bằng JavaScript có ý nghĩa khác với ý định.
danorton

10
2 ^ 31 là cách người ta viết hai đến ba mươi mốt năng lực bằng tiếng Anh. Nó không nằm trong một khối mã. Bạn có phàn nàn về ai đó sử dụng một; trong một câu trả lời, bởi vì đó là một nhân vật có ý nghĩa khác trong Javascript?
lmm

3
Mặc dù người ta nên viết 2³¹ chứ không phải 2 ^ 31 bằng văn bản đơn giản để làm như vậy, bởi vì hầu hết các bố cục bàn phím không có các ký tự theo mặc định. Ít nhất tôi không có bất kỳ vấn đề nào trong việc hiểu ý nghĩa của câu trả lời này.
Jocke

6

Tại thời điểm viết bài, JavaScript đang nhận một loại dữ liệu mới : BigInt. Đó là một đề xuất TC39 ở giai đoạn 4 được đưa vào EcmaScript 2020 . BigIntcó sẵn trong Chrome 67+, FireFox 68+, Opera 54 và Node 10.4.0. Nó đang được tiến hành trong Safari, et al ... Nó giới thiệu các chữ số có hậu tố "n" và cho phép độ chính xác tùy ý:

var a = 123456789012345678901012345678901n;

Tất nhiên, độ chính xác vẫn sẽ bị mất, khi một số như vậy (có thể vô tình) bị ép buộc thành một kiểu dữ liệu số.

Và rõ ràng, sẽ luôn có những giới hạn chính xác do bộ nhớ hữu hạn và chi phí về thời gian để phân bổ bộ nhớ cần thiết và thực hiện số học trên những số lượng lớn như vậy.

Chẳng hạn, việc tạo một số có một trăm nghìn chữ số thập phân, sẽ có độ trễ đáng chú ý trước khi hoàn thành:

console.log(BigInt("1".padEnd(100000,"0")) + 1n)

...nhưng nó đã có tác dụng.


4

Tôi đã thực hiện một thử nghiệm đơn giản với công thức, X- (X + 1) = - 1 và giá trị lớn nhất của XI có thể hoạt động trên Safari, Opera và Firefox (thử nghiệm trên OS X) là 9e15. Đây là mã tôi đã sử dụng để thử nghiệm:

javascript: alert(9e15-(9e15+1));

1
Lưu ý rằng 9e15 = 2 ^ 53 (xem câu trả lời của @ Jimmy).
Nêm

6
9e15 = 9000000000000000. 2 ^ 53 = 9007199254740992. Do đó, là phạm vi, 9e15 chỉ xấp xỉ bằng 2 ^ 53 (có hai chữ số có nghĩa).
devios1

@chaiguy Trong 9000000000000000đó có 1 con số đáng kể. trong `9007199254740992` có 15 con số đáng kể.
Royi Namir

@RoyiNamir Không muốn bắt đầu một cuộc tranh luận vô nghĩa ở đây, nhưng 9000000000000000 có 16 chữ số có nghĩa. Nếu bạn chỉ muốn 1, nó sẽ phải được viết là 9x10 ^ 15.
devios1

1
@chaiguy Số 9000000000000000như nó là - có 1SF. trong đó 90*10^14có 2. ( sigfigscalculator.appspot.com ) & mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htmlm (phần dưới cùng)
Royi Namir

3

Tôi viết nó như thế này:

var max_int = 0x20000000000000;
var min_int = -0x20000000000000;
(max_int + 1) === 0x20000000000000;  //true
(max_int - 1) < 0x20000000000000;    //true

Tương tự cho int32

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;

3

Hãy đi đến các nguồn

Sự miêu tả

Các MAX_SAFE_INTEGERhằng số có giá trị 9007199254740991(9,007,199,254,740,991 hoặc ~ 9 nghìn triệu triệu). Lý do đằng sau con số đó là JavaScript sử dụng các số định dạng dấu phẩy động có độ chính xác kép như được chỉ định trong IEEE 754 và chỉ có thể biểu thị một cách an toàn các số giữa -(2^53 - 1)2^53 - 1 .

An toàn trong ngữ cảnh này đề cập đến khả năng thể hiện chính xác các số nguyên và so sánh chính xác chúng. Ví dụ, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2sẽ đánh giá là đúng, về mặt toán học không chính xác. Xem Number.isSafeInteger () để biết thêm thông tin.

Bởi vì MAX_SAFE_INTEGERlà một thuộc tính tĩnh của Số , bạn luôn sử dụng nó như Number.MAX_SAFE_INTEGERlà một thuộc tính của đối tượng Số mà bạn đã tạo.

Tính tương thích của trình duyệt web

nhập mô tả hình ảnh ở đây




-1

Scato wrote:

bất cứ điều gì bạn muốn sử dụng cho các hoạt động bitwise phải nằm trong khoảng 0x80000000 (-2147483648 hoặc -2 ^ 31) và 0x7fffffff (2147483647 hoặc 2 ^ 31 - 1).

Bảng điều khiển sẽ cho bạn biết rằng 0x80000000 bằng +2147483648, nhưng 0x80000000 & 0x80000000 bằng -2147483648

Hex-Decimals là các giá trị dương không dấu, vì vậy 0x80000000 = 2147483648 - đó là chính xác về mặt toán học. Nếu bạn muốn biến nó thành một giá trị đã ký, bạn phải chuyển sang phải: 0x80000000 >> 0 = -2147483648. Bạn cũng có thể viết 1 << 31.


-7

Firefox 3 dường như không có vấn đề gì với số lượng khổng lồ.

1e + 200 * 1e + 100 sẽ tính tiền phạt thành 1e + 300.

Safari dường như không có vấn đề với nó là tốt. (Đối với bản ghi, đây là trên máy Mac nếu có ai khác quyết định kiểm tra điều này.)

Trừ khi tôi bị mất não vào thời điểm này trong ngày, đây là cách lớn hơn số nguyên 64 bit.


18
nó không phải là số nguyên 64 bit, số dấu phẩy động 64 bit, trong đó 52/53 bit là phần nguyên. do đó, nó sẽ xử lý lên đến 1e300, nhưng không chính xác.
Jimmy

4
Jimmy là chính xác. Hãy thử điều này trong trình duyệt hoặc dòng lệnh JS của bạn:100000000000000010 - 1 => 100000000000000020
Ryan

-7

Cả Node.js và Google Chrome dường như đều đang sử dụng các giá trị dấu phẩy động 1024 bit, vì vậy:

Number.MAX_VALUE = 1.7976931348623157e+308

1
-1: số có thể biểu thị tối đa (không chính xác) có thể là ~ 2 ^ 1024, nhưng điều đó không có nghĩa là chúng bị lệch so với tiêu chuẩn 64 -bit của IEEE-754 .
Roy Tinker

2
TỐI ĐA? Ý bạn là MAX_VALUE?
Raul Guiu

3
đó là tối đa của một giá trị điểm nổi . Điều đó không có nghĩa là bạn có thể lưu trữ một int dài
phuclv

1
Hoặc nhiều hơn vào vấn đề, bạn có thể không đáng tin cậy lưu trữ một int lâu mà không làm mất độ chính xác . 2^53được gọi là MAX_SAFE_INTbởi vì ở trên điểm đó các giá trị trở thành xấp xỉ, theo cùng một cách phân số.
IMSoP
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.