Кажется, что встроенный в JavaScript метод Number () возвращает неправильное значение - PullRequest
0 голосов
/ 10 декабря 2018

Я сделал программу для преобразования баз чисел.Я подумал, что в случае, если в выводе нет символов A-F, было бы удобно возвращать число в виде числа вместо строки (даже если бы я возвращал числа с основанием 2 как обычные десятичные числа,без разницы).

По какой-то причине, когда я конвертировал A3B2 32 в двоичный файл (который должен быть 1010000110101100100 2 [ Wolfram | Alpha source]) Я получил 1010000110101100200.Там есть два, это не бинарный!Последняя строка кода, которая возвращает значение:

return (toBase <= 10) ? Number(result) : result;

Это работало корректно практически для всех тестов, пока я не решил использовать это число base-32 выше.Я думал, что моя программа неправильно выполняла шаг деления / остатка, поэтому я распечатал результат непосредственно перед тем, как он возвращает значение.Это было правильно выдавать 1010000110101100100.Итак, я протестировал метод Number() прямо в консоли Chrome.Вот что произошло:

> Number("1010000110101100100")
> 1010000110101100200

Не понимаю ли я, что делает метод Number()?Почему он преобразует строку, состоящую из всех единиц и нулей, в число с единицами, нулями и Twos ?

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

@ AnonymusSB сказал, что это правильно.Я хочу добавить несколько деталей к нему.

Так что, когда вы Number(value), он внутренне вызывает ToNumber для вычисления значения.когда вы поставляете строку.он имеет двухэтапный процесс для изменения его числа.

  1. Сначала он вычисляет Mathematical value (MV) строки.
  2. Во втором процессе он округляет вычисленное значение. (когда выпревышать предел Math.MAX_SAFE_INTEGER это округление числа).

console.log(Number("9007199254740996"))
console.log(Number("9007199254740997"), "rounded down")
console.log(Number("9007199254740998"))
console.log(Number("9007199254740999") ,"rounded up")

EcmaScript

0 голосов
/ 10 декабря 2018

То, что вы делаете, когда звоните Number("1010000110101100100"), передает строку, которую пытается превратить в число, но это число больше, чем может рассчитать JavaScript, что составляет 9 007 199 254 740 991 (также известный как Number.MAX_SAFE_INTEGER)

В принципе, любое число свыше 9 007 199 254 740 991 не может быть надежно использовано, поскольку JavaScript использует чисел с плавающей запятой с двойной точностью , как указано в IEEE 754

Вот несколько примеров, следующие входные числа «должны» совпадать с выходными, но не потому, что они прошли MAX_SAFE_INTEGER.Некоторые из них есть, но они ненадежны, как показано в разделе Bonus Fun с БОЛЬШИМИ числами ниже.

Number("9007199254740992") // 9007199254740992
Number("9007199254740993") // 9007199254740992
Number("9007199254740994") // 9007199254740994
Number("9007199254740995") // 9007199254740996
Number("9007199254740996") // 9007199254740996
Number("9007199254740997") // 9007199254740996
Number("9007199254740998") // 9007199254740998
Number("9007199254740999") // 9007199254741000

Если вы все еще хотите преобразовать шестнадцатеричный код в двоичный, вам нужно использовать parseInt и Number.prototype.toString и сохраните его как строку.

const hex = "A3B2";
const binary = parseInt(hex, 16).toString(2);
console.log(binary);

Bonus Fun с большими номерами

Следующее верно!

console.log(9007199254740992 === 9007199254740993);
console.log(1010000110101100200 === 1010000110101100100)

Документация

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString

...