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





html lista (20)


Vamos para as Number.MAX_SAFE_INTEGER

Descrição

A constante MAX_SAFE_INTEGER tem um valor 9007199254740991 (9,007,199,254,740,991 ou ~ 9 quadrilhões). O raciocínio por trás desse número é que o JavaScript usa Wiki conforme especificado no IEEE 754 e só pode representar com segurança números entre -(253 - 1) e 253 - 1 .

Seguro neste contexto refere-se à capacidade de representar inteiros exatamente e compará-los corretamente. Por exemplo, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 será avaliado como true, o que é matematicamente incorreto. Veja Number.isSafeInteger() para mais informações.

Como MAX_SAFE_INTEGER é uma propriedade estática de Number , você sempre a usa como Number.MAX_SAFE_INTEGER , em vez de como uma propriedade de um objeto Number criado por você.

Compatibilidade do navegador

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




No momento da escrita, o JavaScript está recebendo um novo tipo de dados: BigInt . É uma proposta do TC39 no estágio 3 . BigInt foi lançado no Chrome e está em andamento no Node, Firefox e Safari ... Ele introduz literais numéricos com um sufixo "n" e permite precisão arbitrária:

var a = 123456789012345678901012345678901n;

A precisão ainda será perdida, é claro, quando tal número for (talvez involuntariamente) forçado a um tipo de dados numéricos.




Number.MAX_VALUE representa o valor numérico máximo representável em JavaScript.

Como ninguém parece ter dito isso, no motor v8 há uma diferença de comportamento para o número e número de 31 bits acima disso.

Se você tem 32 bits você pode usar o primeiro bit para informar ao mecanismo de javascript que tipo de dado é e que os bits restantes contêm os dados reais. Isso é o que o V8 faz como uma pequena otimização para numbers 31 bis (ou costumava fazer, minhas fontes são bastante antigas). Você tem os últimos 31 bits sendo o valor numérico e, em seguida, o primeiro bit informando ao mecanismo se é um número ou uma referência de objeto.

No entanto, se você usar o número acima de 31 bits , os dados não caberão, o número será encaixado em 64 bits e a otimização não estará lá.

A linha inferior, no vídeo abaixo, é:

prefira valores numéricos que podem ser representados como inteiros assinados de 31bits .




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




ECMAScript 6:

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



Experimentar:

maxInt = -1 >>> 1

No Firefox 3.6 é 2 ^ 31 - 1.




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




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



É 2 53 == 9 007 199 254 740 992. Isso ocorre porque os Number s são armazenados como ponto flutuante em uma mantissa de 52 bits.

O valor mínimo é -2 53 .

Isso faz algumas coisas divertidas acontecerem

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

E também pode ser perigoso :)

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
}

Outras leituras: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html




Outros podem já ter dado a resposta genérica, mas achei que seria uma boa idéia dar uma maneira rápida de determiná-la:

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

O que me dá 9007199254740992 em menos de um milissegundo no Chrome 30.

Ele testará os poderes de 2 para descobrir qual deles, quando 'adicionado' 1, é igual a ele mesmo.




+/- 9007199254740991

Seção 8 da ECMA - Números

Note que todos os inteiros positivos e negativos cuja magnitude não é maior do que 2 53 são representáveis ​​no tipo Number (na verdade, o inteiro 0 tem duas representações, +0 e -0).

Eles são valores de ponto flutuante de 64 bits, o maior valor integral exato é 2 53 -1 ou 9007199254740991 . No ES6, isso é definido como Number.MAX_SAFE_INTEGER .

Observe que os operadores bitwise e os operadores shift operam em ints de 32 bits, portanto, nesse caso, o número inteiro seguro máximo é 2 31 -1 ou 2147483647.

Teste isso!

var x = 9007199254740992;
var y = -x;
x == x + 1; // true !
y == y - 1; // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
x / 2;      // 4503599627370496
x >> 1;     // 0
x | 1;      // 1

Nota técnica sobre o assunto do número 9007199254740992: Existe uma representação IEEE-754 exata desse valor, e você pode atribuir e ler esse valor de uma variável, portanto, para aplicativos escolhidos com muito cuidado no domínio de números inteiros menores ou iguais a esse valor, você poderia tratar isso como um valor máximo.

No caso geral, você deve tratar este valor IEEE-754 como inexato, porque é ambíguo se ele está codificando o valor lógico 9007199254740992 ou 9007199254740993.




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.




No JavaScript incorporado do Google Chrome, você pode ir para aproximadamente 2 ^ 1024 antes que o número seja chamado de infinito.




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.




O Node.js e o Google Chrome parecem estar usando valores de ponto flutuante de 1024 bits, portanto:

Number.MAX_VALUE = 1.7976931348623157e+308






A resposta de Jimmy representa corretamente o espectro inteiro de JavaScript contínuo como -9007199254740992 a 9007199254740992 inclusive (desculpe 9007199254740993, você pode pensar que é 9007199254740993, mas está errado! Demonstração abaixo ou em jsfiddle ).

document.write(9007199254740993);

No entanto, não há resposta que encontre / prove isso de forma programática (além do que o CoolAJ86 aludiu em sua resposta que terminaria em 28.56 anos;), então aqui está uma maneira um pouco mais eficiente de fazer isso (para ser mais preciso, é mais eficiente). por cerca de 28,559999999968312 anos :), juntamente com um violino teste :

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




Tudo o que você deseja 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.




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



jQuery é uma biblioteca de manipulação de DOM.

O AngularJS é um framework MV *.

Na verdade, o AngularJS é uma das poucas estruturas JavaScript MV * (muitas ferramentas JavaScript MVC ainda se enquadram na biblioteca de categorias).

Sendo um framework, ele hospeda seu código e toma posse de decisões sobre o que chamar e quando!

O próprio AngularJS inclui uma edição jQuery-lite dentro dele. Portanto, para alguma seleção / manipulação DOM básica, você realmente não precisa incluir a biblioteca jQuery (ela salva muitos bytes para serem executados na rede).

AngularJS tem o conceito de "diretivas" para manipulação de DOM e projetar componentes de interface do usuário reutilizáveis, portanto, você deve usá-lo sempre que sentir necessidade de fazer coisas relacionadas à manipulação DOM (diretivas são apenas locais onde você deve escrever o código jQuery ao usar AngularJS).

O AngularJS envolve alguma curva de aprendizado (mais que jQuery :-).

-> Para qualquer desenvolvedor vindo do background do jQuery, meu primeiro conselho seria "aprender JavaScript como uma linguagem de primeira classe antes de pular para um framework rico como o AngularJS!" Eu aprendi o fato acima da maneira mais difícil.

Boa sorte.





javascript math browser cross-browser