math Qual é o valor inteiro mais alto do JavaScript que um número pode acessar sem perder precisão?





11 Answers

> = ES6: Number.MIN_SAFE_INTEGER; Number.MAX_SAFE_INTEGER; Number.MIN_SAFE_INTEGER; Number.MAX_SAFE_INTEGER;

<= ES5

A partir da referência : Number.MAX_VALUE; Number.MIN_VALUE; Number.MAX_VALUE; Number.MIN_VALUE;

console.log('MIN_VALUE', Number.MIN_VALUE);
console.log('MAX_VALUE', Number.MAX_VALUE);

console.log('MIN_SAFE_INTEGER', Number.MIN_SAFE_INTEGER); //ES6
console.log('MAX_SAFE_INTEGER', Number.MAX_SAFE_INTEGER); //ES6

javascript math browser cross-browser

Isso é definido pela linguagem? Existe um máximo definido? É diferente em diferentes navegadores?




Em JavaScript, existe um número chamado Infinity .

Exemplos:

(Infinity>100)
=> true

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

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

Isso pode ser suficiente para algumas perguntas sobre esse tópico.




Estar seguro

var MAX_INT = 4294967295;

Raciocínio

Eu pensei que seria inteligente e encontraria o valor em que x + 1 === x com uma abordagem mais pragmática.

Minha máquina só pode contar 10 milhões por segundo ou mais ... então vou postar de volta com a resposta definitiva em 28,56 anos.

Se você não pode esperar tanto tempo, estou disposto a apostar que

  • A maioria dos seus loops não funciona por 28,56 anos
  • 9007199254740992 === Math.pow(2, 53) + 1 é prova suficiente
  • Você deve se ater ao 4294967295 que é Math.pow(2,32) - 1 para evitar problemas esperados com bit-shifting

Encontrando 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);
}());



A resposta curta é "depende".

Se você estiver usando operadores bit a bit em qualquer lugar (ou se você estiver se referindo ao comprimento de um Array), os intervalos serão:

Não assinado: 0…(-1>>>0)

Assinado: (-(-1>>>1)-1)…(-1>>>1)

(Acontece que os operadores bit a bit e o comprimento máximo de uma matriz são restritos a inteiros de 32 bits.)

Se você não estiver usando operadores bit a bit ou trabalhando com comprimentos de matriz:

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

Essas limitações são impostas pela representação interna do tipo “Número”, que geralmente corresponde à representação de ponto flutuante de precisão dupla IEEE 754. (Observe que, diferentemente de números inteiros com sinal típico, a magnitude do limite negativo é a mesma que a magnitude do limite positivo, devido às características da representação interna, que na verdade inclui um 0 negativo !)




Muitas respostas anteriores mostram o resultado true de 9007199254740992 === 9007199254740992 + 1
para dizer que 9 007 199 254 740 991 é o número inteiro seguro máximo.

E se continuarmos fazendo acumulação:

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

Pudemos descobrir, entre números maiores que 9 007 199 254 740 992 , apenas números pares são representáveis .

É uma entrada para explicar como o formato binário de 64 bits de precisão dupla funciona nisso. Vamos ver como 9 007 199 254 740 992 é mantido (representado) usando este formato binário.

Começamos de 4 503 599 627 370 496 com a versão resumida do formato primeiro:

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

No lado esquerdo da flecha, temos o bit valor 1 , e um ponto radix adjacente, então multiplicando 2^52 , nós movemos o ponto radix 52 passos, e ele vai para o final. Agora temos 4503599627370496 em binário.

Agora começamos a acumular 1 para esse valor até que todos os bits estejam definidos como 1, o que equivale a 9 007 199 254 740 991 em decimal.

  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. 

Agora, como no formato binário de 64 bits de precisão dupla , ele distribui 12 bits para a fração, não há mais bits disponíveis para adicionar mais 1, então o que podemos fazer é definir todos os bits como 0 e manipular a parte exponente:

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

Agora nós pegamos o 9 007 199 254 740 992 , e com um número maior que ele, o que o formato poderia conter é 2 vezes da fração :

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

Assim, quando o número chegar a 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, apenas 4 vezes a fração poderia ser mantida:

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

Como sobre o número entre [ 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  --|

O valor do bit 1 após o ponto de radix é exatamente igual a 2 ^ -1. (= 1/2, = 0.5) Assim, quando o número menor que 4 503 599 627 370 496 (2 ^ 52), há um bit disponível para representar as 1/2 vezes do inteiro :

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

Menos de 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"

E qual é o alcance disponível da parte expoente ? o formato atribui 11 bits para isso. Formato completo do Wiki : (Para mais detalhes, por favor, vá lá)

Então, para ganhar 2 ^ 52 na parte exponente, precisamos definir e = 1075.




Eu fiz um teste simples com uma fórmula, X- (X + 1) = - 1, e o maior valor de XI pode começar a funcionar no Safari, Opera e Firefox (testado no OS X) é 9e15. Aqui está o código que usei para testar:

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



Eu escrevo assim:

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

O mesmo que int32

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



Scato escreve:

qualquer coisa que você queira usar para operações bit a bit deve estar entre 0x80000000 (-2147483648 ou -2 ^ 31) e 0x7fffffff (2147483647 ou 2 ^ 31 - 1).

o console informará que 0x80000000 é igual a +2147483648, mas 0x80000000 e 0x80000000 é igual a -2147483648

Decimais hexadecimais são valores positivos não assinados, então 0x80000000 = 2147483648 - isso é matematicamente correto. Se você quiser torná-lo um valor assinado, você tem que deslocar para a direita: 0x80000000 >> 0 = -2147483648. Você pode escrever 1 << 31 também.




Basicamente, o javascript não suporta muito tempo.
Portanto, para valores normais que podem representar menos de 32 bits, ele usará o contêiner do tipo int. para valores inteiros maiores que 32 bits, seus usos duplicam. Na representação dupla, a parte inteira é de 53 bits e o resto é mantissa (para manter as informações de ponto flutuante).
então você pode usar 2^53 - 1 9007199254740991 cujo valor é 9007199254740991
você pode acessar o valor para usar em seu código por Number.MAX_SAFE_INTEGER







O Firefox 3 não parece ter problemas com números enormes.

1e + 200 * 1e + 100 calculará bem para 1e + 300.

Safari parece não ter nenhum problema com isso também. (Para o registro, isso é em um Mac, se alguém decide testar isso.)

A menos que eu tenha perdido meu cérebro a esta hora do dia, isso é muito maior do que um inteiro de 64 bits.






Related