Vejamos duas perguntas primeiro:
0,1 + 0,2 == 0,3; // false
999999999999999999999 == 100000000000000000; // verdadeiro
O primeiro problema é a precisão dos decimais, que foi discutido em muitos blogs da indústria. O segundo problema foi que, no ano passado, quando um banco de dados sistemático estava corrigindo os dados, constatou que alguns dados eram duplicados. Este artigo começará a partir da norma e resumirá os problemas acima.
Inteiro máximo
Os números em JavaScript são armazenados usando números de ponto flutuante de 64 bits IEEE 754, e seu formato é:
sxmx 2^e
S é um bit de sinal, indicando positivo e negativo. M é a Mantissa, com 52 bits. E é o expoente, com 11 bits. Na especificação do ECMAScript, o intervalo fornecido por E é [-1074, 971]. Dessa maneira, é fácil deduzir que o número inteiro máximo que JavaScript pode representar é:
1 x (2^53 - 1) x 2^971 = 1.7976931348623157e+308
Este valor é número.max_value
Da mesma forma, o valor do número.Min_Value pode ser deduzido como:
1 x 1 x 2^(-1074) = 5e-324
Observe que o min_value representa o número positivo mais próximo de 0, não o menor número. O menor número é -number.max_value
A precisão do decimal é perdida
Os números de JavaScript são números de ponto flutuante de precisão dupla e são armazenados em binário em computadores. Quando o número de bits significativos exceder 52 bits, haverá perda de precisão. por exemplo:
O binário de decimal 0,1 é 0,0 0011 0011 0011… (loop 0011)
O binário de decimal 0,2 é 0,0011 0011 0011… (loop 0011)
0,1 + 0,2 A adição pode ser expressa como:
e = -4; M = 1.10011001100 ... 1100 (52 bits)
+ e = -3; M = 1.10011001100 ... 1100 (52 bits)
--------------------------------------------------------------------------------------------------------------------------------------------------
e = -3; M = 0,11001100110 ... 0110
+ e = -3; M = 1.10011001100 ... 1100
--------------------------------------------------------------------------------------------------------------------------------------------------
e = -3; M = 10.01100110011 ... 001
--------------------------------------------------------------------------------------------------------------------------------------------------
= 0,01001100110011 ... 001
= 0,3000000000000000004 (decimal)
Com base no cálculo acima, também podemos tirar uma conclusão: quando o número finito de decimais decimais na representação binária não exceder 52 bits, ele pode ser armazenado com precisão no JavaScript. por exemplo:
0,05 + 0,005 == 0,055 // true
Outras regras, como:
0,05 + 0,2 == 0,25 // true
0,05 + 0,9 == 0,95 // false
Os modos de arredondamento do IEEE 754 precisam ser considerados, e aqueles interessados podem estudá -lo ainda mais.
A precisão dos números inteiros grandes está perdida
Esta questão raramente é mencionada. Primeiro, temos que descobrir qual é o problema:
1. Qual é o número inteiro máximo que o JavaScript pode armazenar?
Esta pergunta foi respondida anteriormente e é número.max_value, um número muito grande.
2. Qual é o número inteiro máximo que o JavaScript pode armazenar sem perder precisão?
De acordo com o SXMX 2^E, o bit de sinal é positivo, o Mantissa de 52 bits é totalmente acolchoado com 1 e o expoente E é o valor máximo de 971. Obviamente, a resposta ainda é número.max_value.
Qual é exatamente o nosso problema? Volte ao código inicial:
999999999999999999999 == 100000000000000000; // verdadeiro
É óbvio que 16 9s são muito inferiores a 308 10s. Esse problema não tem nada a ver com max_value e deve ser atribuído ao Mantis M com apenas 52 dígitos.
Pode ser descrito no código:
var x = 1; // Para reduzir a quantidade de cálculo, o valor inicial pode ser definido como maior, como Math.pow (2, 53) - 10
while (x! = x+1) x ++;
// x = 9007199254740992, ou seja, 2^53
Ou seja, quando x é menor ou igual a 2^53, é garantido que a precisão de x não seja perdida. Quando x é maior que 2^53, a precisão de x pode ser perdida. por exemplo:
Quando x é 2^53 + 1, sua representação binária é:
100000000000 ... 001 (existem 52 0s no meio)
Ao armazenar com números de ponto flutuante de precisão dupla:
e = 1; M = 10000..00 (total 52 0s, 1 é o bit oculto)
Obviamente, é o mesmo que 2^53 armazenamento.
De acordo com a idéia acima, pode -se descrever que, por 2^53 + 2, seu binário é 100000… 0010 (51 0s no meio) e também pode ser armazenado com precisão.
Regra: quando x é maior que 2^53 e o número de dígitos significativos binários é superior a 53 bits, haverá perda de precisão. Isso é essencialmente o mesmo que a perda de precisão de decimais.
O bit oculto pode ser usado para referência: um tutorial sobre o tipo duplo Java.
resumo
A precisão de decimais e números inteiros grandes não é perdida apenas em JavaScript. Estritamente falando, qualquer linguagem de programação (C/C ++/C#/Java, etc.) que usa o formato do número de ponto flutuante IEEE 754 para armazenar tipos de pontos flutuantes, com problemas de perda de precisão. Em C# e Java, são fornecidas classes de encapsulamento decimal e bigdecimal para executar o processamento correspondente, para evitar a perda de precisão.
Nota: Já existe uma proposta decimal na especificação do ECMAScript, mas ainda não foi oficialmente adotada.
Finalmente, teste a todos:
Número.max_value + 1 == numer.max_value;
Número.max_value + 2 == numer.max_value;
...
Número.max_value + x == numer.max_value;
Número.max_value + x + 1 == infinito;
...
Número.max_value + número.max_value == infinito;
// pergunta:
// 1. Qual é o valor de x?
// 2. Infinity - número.max_value == x + 1; é verdadeiro ou falso?
A breve discussão acima sobre a perda de precisão de decimais e grandes números inteiros em JavaScript é todo o conteúdo que compartilho com você. Espero que você possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.