Apa nilai integer tertinggi JavaScript yang bisa digunakan angka tanpa kehilangan presisi?

951

Apakah ini ditentukan oleh bahasa? Apakah ada maksimum yang ditentukan? Apakah berbeda di browser yang berbeda?

TALlama
sumber
5
Anda tidak perlu bergantung pada batas JS dengan pustaka seperti github.com/MikeMcl/big.js , lihat misalnya di sini untuk uji reliabilitasnya
Dmitri Zaitsev
2
apa nilai integer tertinggi yang dapat Anda gunakan dengan big.js?
George
@ George Di sini adalah big.js API: mikemcl.github.io/big.js/#dp
simhumileco
Pertanyaan itu tidak masuk akal. Apa artinya angka "menuju ke" nilai integer? Jika Anda hanya ingin bertanya apa bilangan bulat tertinggi yang dapat Anda wakili dalam JS, angka tertinggi (hingga) itu sendiri adalah bilangan bulat.
Veky
@DmitriZaitsev Kita tidak perlu lagi bergantung pada perpustakaan eksternal (setidaknya pada beberapa browser). 1n << 10000nadalah bilangan bulat yang benar-benar besar, tanpa kehilangan presisi, tanpa memerlukan dependensi (dan tidak perlu dikatakan, bahkan tidak mendekati batas).
Amadan

Jawaban:

868

JavaScript memiliki dua tipe angka: Numberdan BigInt.

Jenis nomor yang paling sering digunakan Number,, adalah 64-bit floating point nomor IEEE 754 .

Nilai integral pasti terbesar dari jenis ini adalah Number.MAX_SAFE_INTEGER, yaitu:

  • 2 53 -1, atau
  • +/- 9.007.199.254.740.991, atau
  • sembilan kuadriliun tujuh triliun seratus sembilan puluh sembilan miliar dua ratus lima puluh empat juta tujuh ratus empat puluh ribu sembilan ratus sembilan puluh satu

Untuk menempatkan ini dalam perspektif: satu kuadriliun byte adalah petabyte (atau seribu terabyte).

"Aman" dalam konteks ini mengacu pada kemampuan untuk mewakili bilangan bulat dengan tepat dan membandingkannya dengan benar.

Dari spec:

Perhatikan bahwa semua bilangan bulat positif dan negatif yang besarnya tidak lebih besar dari 2 53 dapat diwakili dalam Numbertipe (memang, bilangan bulat 0 memiliki dua representasi, +0 dan -0).

Untuk menggunakan bilangan bulat yang lebih besar dari ini dengan aman, Anda harus menggunakan BigIntyang tidak memiliki batas atas

Perhatikan bahwa operator bitwise dan operator shift beroperasi pada bilangan bulat 32-bit, jadi dalam kasus itu, bilangan bulat aman max adalah 2 31 -1, atau 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


Catatan teknis tentang masalah angka 9.007.199.254.740.992: Ada representasi IEEE-754 yang tepat dari nilai ini, dan Anda dapat menetapkan dan membaca nilai ini dari variabel, jadi untuk aplikasi yang dipilih dengan sangat hati-hati dalam domain bilangan bulat kurang dari atau sama dengan nilai ini, Anda bisa memperlakukan ini sebagai nilai maksimum.

Dalam kasus umum, Anda harus memperlakukan nilai IEEE-754 ini sebagai tidak eksak, karena tidak jelas apakah itu mengkodekan nilai logis 9,007,199,254,740,992 atau 9,007,199,254,740,993.

Jimmy
sumber
75
Ini sepertinya benar, tetapi apakah ada tempat di mana ini didefinisikan, á la C's MAX_INT atau Java's Integer.MAX_VALUE?
TALlama
48
4294967295 === Math.pow(2,32) - 1;
CoolAJ86
13
Jadi apa bilangan bulat terkecil dan terbesar yang dapat kita gunakan untuk memastikan presisi yang tepat?
Pacerier
38
Mungkin perlu dicatat bahwa tidak ada aktual (int) di javascript. Setiap instance dari Number adalah (float) atau NaN.
Beetroot-Beetroot
53
9007199254740992 bukan benar-benar nilai maksimum, bit terakhir di sini sudah dianggap nol dan Anda telah kehilangan 1 bit presisi. Nomor aman sebenarnya adalah 9007199254740991 (Number.MAX_SAFE_INTEGER)
Willem D'Haeseleer
461

> = ES6:

Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;

<= ES5

Dari referensi :

Number.MAX_VALUE;
Number.MIN_VALUE;

Peter Bailey
sumber
23
Saya telah mengedit pertanyaan menjadi sedikit lebih tepat tentang keinginan nilai Integer max, bukan hanya nilai Number max. Maaf atas kebingungannya, di sini.
TALlama
5
Apakah hasil yang dikembalikan dijamin sama di semua browser?
Pacerier
7
Perhatikan bahwa itu Number.MIN_VALUEadalah angka positif sekecil mungkin . Nilai terkecil (yaitu kurang dari yang lain) mungkin -Number.MAX_VALUE.
Michael Scheper
34
ES6 memperkenalkan Number.MIN_SAFE_INTEGERdanNumber.MAX_SAFE_INTEGER
superlukas
2
Jadi, dalam hal ini, haruskah kita memilih jawaban karena salah untuk pertanyaan yang diperbarui, atau meninggalkannya karena Peter Baily benar pada saat jawabannya dijawab?
Rocketsarefast
112

Ini adalah 2 53 == 9 007 199 254 740 992. Ini karena Numbers disimpan sebagai floating-point dalam mantissa 52-bit.

Nilai minimumnya adalah -2 53 .

Ini membuat beberapa hal menyenangkan terjadi

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

Dan juga bisa berbahaya :)

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
}

Bacaan lebih lanjut: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

Vjeux
sumber
1
meskipun orang tidak akan pernah mencapai akhir itu untuk loop dalam jangka waktu yang waras, Anda mungkin ingin mengatakani += 1000000000
ninjagecko
2
@ninjagecko, dia mulai di MAX_INT sehingga akhirnya ada di sana. Juga menggunakan i + = 1000000000 akan membuatnya tidak lagi menjadi infinite loop. Cobalah.
Ted Bigham
@ TedBigham: Ah oops, sudah siap terlalu cepat melalui itu. Terima kasih telah mengoreksi saya dua kali.
ninjagecko
Lihat argumen Jimmy untuk 9.007.199.254.740.991, bukan 9.007.199.254.740.992 di sini . Itu, dikombinasikan dengan tindak lanjut saya, tampaknya persuasif.
TJ Crowder
60

Dalam JavaScript, ada nomor yang disebut Infinity.

Contoh:

(Infinity>100)
=> true

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

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

Ini mungkin cukup untuk beberapa pertanyaan tentang topik ini.

BananaNeil
sumber
25
Sesuatu mengatakan kepada saya infinity tidak memenuhi syarat sebagai bilangan bulat. :)
devios1
7
Tapi itu cukup bagus untuk menginisialisasi minvariabel ketika Anda mencari nilai minimum.
djjeck
9
Perhatikan bahwaInfinity - 1 === Infinity
H.Wolper
2
juga (Infinity <100) => false dan Math.pow (2,1024) === Infinity
Sijav
6
Juga tidak ada nilainya yang dapat menangani Infinity negatif juga. Jadi1 - Infinity === -Infinity
dmccabe
41

Jawaban Jimmy benar mewakili spektrum bilangan bulat JavaScript terus menerus sebagai -9007199254740992 ke 9007199254740992 inklusif (maaf 9007199254740993, Anda mungkin berpikir Anda 9007199254740993, tetapi Anda salah! Demonstrasi di bawah atau di jsfiddle ).

console.log(9007199254740993);

Namun, tidak ada jawaban yang menemukan / membuktikan ini secara terprogram (selain yang CoolAJ86 singgung dalam jawabannya yang akan selesai dalam 28,56 tahun;), jadi inilah cara yang sedikit lebih efisien untuk melakukan itu (tepatnya, lebih efisien) sekitar 28,559999999968312 tahun :), bersama dengan biola uji :

/**
 * 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);

Briguy37
sumber
8
@ CoolAJ86: Lol, saya menantikan 15 Maret 2040. Jika nomor kami cocok, kami harus mengadakan pesta :)
Briguy37
var x = Math.pow (2,53) -3; sementara (x! = x + 1) x ++; -> 9007199254740991
MickLH
@MickLH: Saya mendapatkan 9007199254740992 dengan kode itu . Mesin JavaScript apa yang Anda gunakan untuk menguji?
Briguy37
Anda mendapatkan 9007199254740992 dengan kode Anda sendiri, saya tidak menggunakan nilai akhir x, tetapi evaulasi akhir x ++ untuk alasan paranoid. Google Chrome btw.
MickLH
@MickLH: mengevaluasi x++memberi Anda nilai x sebelum kenaikan terjadi, sehingga mungkin menjelaskan perbedaan. Jika Anda ingin ekspresi mengevaluasi ke hal yang sama dengan nilai akhir x, Anda harus mengubahnya menjadi ++x.
peterflynn
32

Supaya aman

var MAX_INT = 4294967295;

Pemikiran

Saya pikir saya akan menjadi pintar dan menemukan nilai di mana x + 1 === xdengan pendekatan yang lebih pragmatis.

Mesin saya hanya dapat menghitung 10 juta per detik atau lebih ... jadi saya akan mengirim kembali dengan jawaban pasti dalam 28,56 tahun.

Jika Anda tidak bisa menunggu selama itu, saya berani bertaruh itu

  • Sebagian besar loop Anda tidak berjalan selama 28,56 tahun
  • 9007199254740992 === Math.pow(2, 53) + 1 cukup buktinya
  • Anda harus tetap berpegang pada 4294967295hal itu Math.pow(2,32) - 1untuk menghindari masalah yang diharapkan dengan pengalihan bit

Menemukan 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);
}());
CoolAJ86
sumber
4
tidak bisakah kamu memulainya pada 2 ^ 53 - 2 untuk menguji? (ya Anda bisa, saya baru saja mencobanya, bahkan dengan -3 agar aman: var x = Math.pow (2,53) -3; sementara (x! = x +1) x ++;) -> 9007199254740991
MickLH
Jawaban bagus! Selain itu, saya tahu nilainya telah diselesaikan, tetapi mengapa tidak menggunakan pencarian biner untuk menemukan hal itu?
higuaro
1
Apa kesenangannya? Selain itu, @ Briguy37 mengalahkan saya untuk itu: stackoverflow.com/a/11639621/151312
CoolAJ86
perhatikan bahwa MAX_INT 'aman' ini berdasarkan 32 bit tidak akan berfungsi ketika membandingkan dengan nilai Date. 4294967295 begitu kemarin!
Jerry
1
Jawaban "Agar aman: var MAX_INT = 4294967295;" tidak lucu. Jika Anda bukan bitshifting, jangan khawatir tentang hal itu (kecuali jika Anda memerlukan int lebih besar dari 4294967295, dalam hal ini Anda mungkin harus menyimpannya sebagai string dan menggunakan perpustakaan bigint).
CoolAJ86
29

Jawaban singkatnya adalah "itu tergantung."

Jika Anda menggunakan operator bitwise di mana saja (atau jika Anda mengacu pada panjang Array), rentangnya adalah:

Tidak ditandatangani: 0…(-1>>>0)

Tertanda: (-(-1>>>1)-1)…(-1>>>1)

(Kebetulan bahwa operator bitwise dan panjang maksimum array dibatasi untuk bilangan bulat 32-bit.)

Jika Anda tidak menggunakan operator bitwise atau bekerja dengan panjang array:

Tertanda: (-Math.pow(2,53))…(+Math.pow(2,53))

Batasan ini dikenakan oleh representasi internal dari tipe "Number", yang umumnya sesuai dengan representasi floating-point IEEE 754 presisi ganda. (Perhatikan bahwa tidak seperti bilangan bulat yang ditandatangani, besarnya batas negatif sama dengan besarnya batas positif, karena karakteristik representasi internal, yang sebenarnya termasuk negatif 0!)

danorton
sumber
Ini adalah jawaban yang saya ingin temukan pada bagaimana mengkonversi X ke integer 32 bit atau integer unsigned. Putuskan jawaban Anda untuk itu.
Charlie Affumigato
29

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
WaiKit Kung
sumber
1
Waspadalah ini belum didukung oleh semua browser! Hari ini iOS (bahkan tidak chrome), Safari dan IE tidak menyukainya.
cregox
5
Harap baca jawabannya dengan cermat, kami tidak menggunakan implementasi default Number.MAX_SAFE_INTEGER dalam ECMASkrip 6, kami mendefinisikannya dengan Math.pow (2, 53) -1
WaiKit Kung
Saya pikir itu hanya referensi bagaimana penerapannya di ECMA 6! : PI pikir komentar saya masih valid. Semua masalah konteks. ;)
cregox
3
Apakah dapat diandalkan untuk menghitung MAX_SAFE_INTEGERdi semua browser dengan bekerja mundur? Haruskah Anda maju? Yaitu, Number.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) +1
kjv
Apakah Math.pow(2, 53)-1operasi yang aman? Ini lebih besar dari integer aman terbesar.
ioquatix
21

Banyak jawaban dari jaman dulu telah menunjukkan hasil truedari 9007199254740992 === 9007199254740992 + 1untuk memverifikasi bahwa 9 007 199 254 740 991 adalah maksimum dan integer aman.

Bagaimana jika kita terus melakukan akumulasi:

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

Kita bisa mengetahui bahwa di antara angka-angka yang lebih besar dari 9 007 199 254 740 992 , hanya angka genap yang dapat diwakili .

Ini adalah pintu masuk untuk menjelaskan bagaimana format biner 64-bit presisi ganda bekerja pada ini. Mari kita lihat bagaimana 9 007 199 254 740 992 dipegang (diwakili) dengan menggunakan format biner ini.

Menggunakan versi singkat untuk menunjukkannya dari 4 503 599 627 370 496 :

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

Di sisi kiri panah, kita memiliki nilai bit 1 , dan titik radix yang berdekatan , kemudian dengan mengalikan 2^52, kita memindahkan titik radix 52 langkah ke kanan, dan menuju akhir. Sekarang kita mendapatkan 4503599627370496 dalam bentuk biner.

Sekarang kita mulai mengakumulasi 1 ke nilai ini sampai semua bit diatur ke 1, yang sama dengan 9 007 199 254 740 991 dalam desimal.

  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. 

Sekarang, karena dalam format biner 64-bit presisi ganda , ia secara ketat mengalokasikan 52 bit untuk fraksi, tidak ada lagi bit yang tersedia untuk dibawa untuk menambahkan satu lagi 1, jadi yang bisa kita lakukan adalah mengatur semua bit kembali ke 0, dan memanipulasi bagian eksponen:

  |--> 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 --| 

Sekarang kita mendapatkan 9 007 199 254 740 992 , dan dengan jumlah yang lebih besar dari itu, format apa yang bisa menampung adalah 2 kali dari fraksi , itu berarti sekarang setiap 1 penambahan pada bagian pecahan sebenarnya sama dengan 2 penambahan, itu sebabnya dua kali lipat format 64-bit binary tidak dapat menampung angka ganjil ketika jumlahnya lebih besar dari 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 --|

Jadi ketika jumlahnya mencapai lebih dari 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, hanya 4 kali fraksi yang dapat disimpan:

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

Bagaimana dengan angka antara [ 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  --|

Nilai bit 1 setelah titik radix adalah 2 ^ -1 tepatnya. (= 1/2, = 0,5) Jadi ketika angka kurang dari 4 503 599 627 370 496 (2 ^ 52), ada satu bit yang tersedia untuk mewakili 1/2 kali bilangan bulat :

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

Kurang dari 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"

Dan apa kisaran eksponen yang tersedia ? format membagikan 11 bit untuk itu. Format lengkap dari Wiki : (Untuk lebih jelasnya silakan ke sana)

IEEE 754 Double Floating Point Format.svg

masukkan deskripsi gambar di sini

Jadi untuk membuat bagian eksponen menjadi 2 ^ 52, kita harus menetapkan e = 1075.

Carr
sumber
13

Yang lain mungkin sudah memberikan jawaban umum, tetapi saya pikir itu akan menjadi ide yang baik untuk memberikan cara cepat untuk menentukannya:

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

Yang memberi saya 9007199254740992 dalam waktu kurang dari satu milidetik di Chrome 30.

Ini akan menguji kekuatan 2 untuk menemukan yang mana, ketika 'ditambahkan' 1, sama dengan dirinya.

Philippe97
sumber
Mungkin aplikasi Anda rusak, pikir.
Sapphire_Brick
8

Apa pun yang ingin Anda gunakan untuk operasi bitwise harus antara 0x80000000 (-2147483648 atau -2 ^ 31) dan 0x7fffffff (2147483647 atau 2 ^ 31 - 1).

Konsol akan memberi tahu Anda bahwa 0x80000000 sama dengan +2147483648, tetapi 0x80000000 & 0x80000000 sama dengan -2147483648.

Scato
sumber
6

Mencoba:

maxInt = -1 >>> 1

Di Firefox 3.6 itu 2 ^ 31 - 1.

Martin Naatz
sumber
2
@danorton: Saya tidak yakin Anda mengerti apa yang Anda lakukan. ^berarti dinaikkan ke kekuasaan . Di konsol javascript, ^adalah XOR , tidak dinaikkan ke
kumarharsh
2
buka konsol Chrome / Firefox. Tipe 5 ^ 2. Dalam biner, 5 adalah101 dan 2 adalah 010. Sekarang, jika Anda Bitwise XOR mereka, Anda akan 5(101) ^ 2(010) = 7(111) MEMBACA INI JIKA ANDA BINGUNG Apa yang dibahas di sini Math.pow()bukan ^operator
kumarharsh
3
Sekali lagi, saya sama sekali tidak bingung. Saya telah berkomentar dan menurunkan suara pada apa yang ditulis . Jika Math.pow () adalah apa yang dimaksud, maka itulah yang harus ditulis. Dalam menjawab pertanyaan tentang JavaScript, tidak pantas menggunakan sintaksis bahasa yang berbeda. Bahkan lebih tidak pantas untuk menggunakan sintaks yang valid dalam JavaScript, tetapi dengan interpretasi dalam JavaScript yang memiliki arti berbeda dari yang dimaksudkan.
danorton
10
2 ^ 31 adalah bagaimana seseorang menulis dua hingga tiga puluh satu kekuatan dalam bahasa Inggris. Itu tidak ada dalam blok kode. Apakah Anda mengeluh tentang seseorang yang menggunakan; dalam jawaban, karena itu karakter dengan makna berbeda dalam Javascript?
lmm
3
Meskipun seseorang harus menulis 2³¹ dan bukan 2 ^ 31 dalam teks biasa yang biasa dilakukan, karena sebagian besar tata letak keyboard tidak memiliki karakter tersebut secara default. Setidaknya saya tidak memiliki masalah dalam memahami apa yang dimaksud dalam jawaban ini.
Jocke
6

Pada saat penulisan, JavaScript menerima tipe data baru: BigInt. Ini adalah proposal TC39 pada tahap 4 untuk dimasukkan dalam EcmaScript 2020 . BigInttersedia di Chrome 67+, FireFox 68+, Opera 54 dan Node 10.4.0. Ini sedang berlangsung di Safari, dkk ... Ini memperkenalkan literal numerik yang memiliki akhiran "n" dan memungkinkan untuk presisi yang berubah-ubah:

var a = 123456789012345678901012345678901n;

Ketepatan masih akan hilang, tentu saja, ketika angka seperti itu (mungkin tidak sengaja) dipaksa ke tipe data nomor.

Dan, jelas, akan selalu ada keterbatasan presisi karena memori yang terbatas, dan biaya dalam hal waktu untuk mengalokasikan memori yang diperlukan dan untuk melakukan aritmatika pada sejumlah besar tersebut.

Misalnya, pembuatan angka dengan seratus ribu digit desimal, akan mengalami penundaan sebelum selesai:

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

... tapi berhasil.

trincot
sumber
4

Saya melakukan tes sederhana dengan rumus, X- (X + 1) = - 1, dan nilai XI terbesar dapat bekerja di Safari, Opera dan Firefox (diuji pada OS X) adalah 9e15. Berikut adalah kode yang saya gunakan untuk pengujian:

javascript: alert(9e15-(9e15+1));
Raynet
sumber
1
Perhatikan bahwa 9e15 = 2 ^ 53 (lihat jawaban Jimmy).
Wedge
6
9e15 = 9000000000000000. 2 ^ 53 = 9007199254740992. Oleh karena itu untuk menjadi bertele-tele, 9e15 hanya kira-kira sama dengan 2 ^ 53 (dengan dua digit signifikan).
devios1
@chaiguy In 9000000000000000ada 1 angka penting. dalam `9007199254740992` ada 15 angka penting.
Royi Namir
@RoyiNamir Tidak ingin memulai argumen tidak berguna di sini, tetapi 900000000000000000 memiliki 16 digit signifikan. Jika Anda hanya ingin 1, itu harus ditulis sebagai 9x10 ^ 15.
devios1
1
@chaiguy No. 9000000000000000apa adanya - memiliki 1SF. di mana 90*10^14memiliki 2. ( sigfigscalculator.appspot.com ) & mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (bagian bawah)
Royi Namir
3

Saya menulis seperti ini:

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

Sama untuk int32

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;
Jerome
sumber
3

Mari kita ke sumbernya

Deskripsi

The MAX_SAFE_INTEGERkonstan memiliki nilai 9007199254740991(9,007,199,254,740,991 atau ~ 9 kuadriliun). Alasan di balik angka itu adalah bahwa JavaScript menggunakan angka format floating-point presisi ganda seperti yang ditentukan dalam IEEE 754 dan hanya dapat dengan aman mewakili angka antara -(2^53 - 1)dan 2^53 - 1.

Aman dalam konteks ini mengacu pada kemampuan untuk mewakili bilangan bulat dengan tepat dan membandingkannya dengan benar. Misalnya, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2akan mengevaluasi ke true, yang secara matematis salah. Lihat Number.isSafeInteger () untuk informasi lebih lanjut.

Karena MAX_SAFE_INTEGERmerupakan properti statis dari Number , Anda selalu menggunakannya sebagai Number.MAX_SAFE_INTEGER, alih-alih sebagai properti dari objek Number yang Anda buat.

Kompatibilitas browser

masukkan deskripsi gambar di sini

simhumileco
sumber
-1

Scato wrotes:

apa pun yang ingin Anda gunakan untuk operasi bitwise harus antara 0x80000000 (-2147483648 atau -2 ^ 31) dan 0x7fffffff (2147483647 atau 2 ^ 31 - 1).

konsol akan memberi tahu Anda bahwa 0x80000000 sama dengan +2147483648, tetapi 0x80000000 & 0x80000000 sama dengan -2147483648

Hex-Desimal adalah nilai positif yang tidak ditandatangani, jadi 0x80000000 = 2147483648 - itu benar secara matematis. Jika Anda ingin menjadikannya nilai yang ditandatangani, Anda harus menggeser ke kanan: 0x80000000 >> 0 = -2147483648. Anda juga dapat menulis 1 << 31.

SammieFox
sumber
-7

Firefox 3 tampaknya tidak memiliki masalah dengan jumlah yang besar.

1e + 200 * 1e + 100 akan menghitung denda hingga 1e + 300.

Safari tampaknya tidak punya masalah dengan itu juga. (Sebagai catatan, ini ada di Mac jika orang lain memutuskan untuk menguji ini.)

Kecuali saya kehilangan otak pada saat ini, ini jauh lebih besar dari integer 64-bit.

jishi
sumber
18
itu bukan integer 64 bit, itu adalah angka floating point 64-bit, dimana 52/53 bit adalah bagian integer. jadi itu akan menangani hingga 1e300, tetapi tidak dengan presisi yang tepat.
Jimmy
4
Jimmy benar. Coba ini di browser Anda atau baris perintah JS:100000000000000010 - 1 => 100000000000000020
Ryan
-7

Node.js dan Google Chrome tampaknya menggunakan nilai titik apung 1024 bit jadi:

Number.MAX_VALUE = 1.7976931348623157e+308
TinyTimZamboni
sumber
1
-1: angka maksimum yang dapat diwakili (tidak-persis integral) mungkin ~ 2 ^ 1024, tetapi itu tidak berarti mereka menyimpang dari standar IEEE-754 64- bit.
Roy Tinker
2
MAX_INT? Apakah maksud Anda MAX_VALUE?
Raul Guiu
3
itu maksimum dari nilai floating point . Itu tidak berarti bahwa Anda dapat menyimpan int selama itu
phuclv
1
Atau lebih tepatnya, Anda tidak dapat menyimpan int dengan andal selama itu tanpa kehilangan keakuratan . 2^53disebut MAX_SAFE_INTkarena di atas titik itu nilai-nilai menjadi perkiraan, dengan cara yang sama fraksi.
IMSoP