Pergunta

Por que q == 0 está no script a seguir?

<script>
  var start = 1234567890123456789;
  var end =   1234567890123456799;
  var q = end - start;
  alert(q);
</script>

Eu acho que o resultado deveria ser 10.Qual é a maneira correta de subtrair esses dois números?

Foi útil?

Solução

Porque os números no JavaScript são pontos flutuantes. Eles têm precisão limitada.

Quando o JavaScript vê um número muito longo, ele o arredonda para o número mais próximo que pode representar como um bóia de 64 bits. Em seu script, start e end Seja arredondado para o mesmo valor.

alert(1234567890123456789);   // says: 1234567890123456800
alert(1234567890123456799);   // says: 1234567890123456800

Não há uma maneira interna de fazer aritmética precisa em números inteiros grandes, mas você pode usar uma biblioteca Biginteger, como Este.

Outras dicas

Jason já postou o porquê. Para uma solução, você pode obter uma biblioteca Bigint JavaScript em http://www-cs-students.stanford.edu/~tjw/jsbn/

const subtract = (a, b) => [a, b].map(n => [...n].reverse()).reduce((a, b) => a.reduce((r, d, i) => {
    let s = d - (b[i] || 0)
    if (s < 0) {
        s += 10
        a[i + 1]--
    }
    return '' + s + r
}, '').replace(/^0+/, ''))


Use melhor a biblioteca grande inteira para essas coisas para lidar com todos os diferentes casos de teste.

Isso é apenas para o caso geral que você pode usar ....

Está explicado no Documentação JavaScript:

De acordo com o padrão ECMAScript, existe apenas um tipo de número: o valor IEEE 754 de formato binário de 64 bits de precisão dupla (números entre -(253-1) e 253-1). Não existe um tipo específico para números inteiros.

Página da Wikipédia sobre formato de ponto flutuante de precisão dupla explica:

Entre 252= 4,503,599,627,370,496 e 253= 9,007,199,254,740,992 os números representáveis ​​são exatamente os inteiros.Para a próxima faixa, de 253 para 254, tudo é multiplicado por 2, então os números representáveis ​​são os pares, etc.

(Todos os números inteiros menores que 252 são representados exatamente.)

1234567890123456789 e 1234567890123456799 são maiores que 260= 1152921504606846976.Nessa magnitude, apenas cerca de 1% dos números inteiros são armazenados exatamente usando o formato de ponto flutuante de precisão dupla.

Esses dois não podem ser armazenados exatamente.Ambos são arredondados para 1234567890123456800.


O Documentação JavaScript também explica como saber se um número inteiro está armazenado exatamente:

[...] e começando com ECMAScript 6, você também pode verificar se um número está no intervalo de números de ponto flutuante de precisão dupla usando Number.isSafeInteger() assim como Number.MAX_SAFE_INTEGER e Number.MIN_SAFE_INTEGER.Além desse intervalo, os números inteiros em JavaScript não são mais seguros e serão uma aproximação de ponto flutuante de precisão dupla do valor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top