Почему parseInt ('dsff66', 16) возвращает 13?
сегодня я наткнулся на странный (на мой взгляд) дело в JavaScript. Я передал не шестнадцатеричную строку функции parseInt с базой 16 и...Я получил результат. Я ожидал бы, что функция выдаст какое-то исключение или, по крайней мере, вернет NaN, но ей удалось проанализировать его и вернуть int.
мой призыв был:
var parsed = parseInt('dsff66', 16); // note the 's' in the first argument
document.write(parsed);
и вот результат: 13
.
Я заметил, что он" останавливает " синтаксический анализ с первым символом, который не принадлежат к системе счисления, указанной во 2-м аргументе, поэтому вызываем parseInt('fg',16)
Я бы 15
как результат.
на мой взгляд, он должен вернуть Нэн. Может кто-нибудь объяснить мне, почему это не так? Почему кто-то хочет, чтобы эта функция вела себя так (возвращала целое число, даже если это не точное представление переданной строки) ?
4 ответов
почему кто-то хочет, чтобы эта функция вела себя так (возвращала целое число, даже если это не точное представление переданной строки)?
потому что большую часть времени (на сегодняшний день) вы работаете с базовыми числами 10, и в этом случае JS может просто cast - не разбирать-строку на число. (edit: по-видимому, не только base-10; см. обновление ниже.)
поскольку JS динамически типизирован, некоторые строки работают просто отлично как числа без всякой работы с твоей стороны. Например:
"21" / 3; // => 7
"12.4" / 4; // => 3.1
не нужно parseInt
, потому что "21"
и "12.4"
по существу уже являются числами. Однако если строка "12.4xyz"
тогда вы действительно получите NaN
при делении, так как это определенно не число и не может быть неявно брошено или принуждено к одному.
вы также можете явно "бросить" строку в число с Number(someString)
. в то время как он тоже поддерживает только базу 10, он действительно вернется NaN
для недопустимых строк.
так как JS уже имеет неявный и явный тип литья / преобразования / принуждения,parseInt
роль не должна быть еще одной функцией кастинга типа.
parseInt
вместо этого роль должна быть, ну,извлечение
parseInt
считывает входные данные, пока не встретит недопустимый символ, а затем использует все допустимые входные данные, прочитанные до этого недопустимого символа. Подумайте:
parseInt("17days", 10);
это будет использовать вход 17
и опустить все после недействительного d
.
если [входная строка] S содержит любой символ, который не является цифрой radix-R, то пусть Z [строка должна быть целочисленной] подстрока S, состоящая из всех символов перед первым таким символом; в противном случае пусть Z будет с.
в вашем примере s
является недопустимым символом базы-16, поэтому parseInt
использует только ведущие d
.
как почему это поведение было включено: нет способа узнать наверняка, но это, скорее всего, попытка воспроизвести поведение strtol
(string to long)из стандартной библиотеки C. От strtol(3)
man page:
...строка преобразуется в длинное значение int очевидным образом,остановка на первом символе, который не является допустимой цифрой в данную базу.
это соединение дополнительно поддерживается (в некоторой степени) тем, что оба parseInt
и strtol
указаны, чтобы игнорировать ведущие пробелы, и они могут оба принимать ведущий 0x
для шестнадцатеричных значений.
в данном случае parseInt()
интерпретировать письмо от "A"
to "F"
as hexadecimal
и разберите их на десятичные числа. Это значит d
вернутся 13
.
что делает parseInt ()
parseInt("string", radix)
интерпретируйте числа и Буквы в строке как шестнадцатеричные (это зависит от радиуса) в число.parseInt()
только разобрать число или букву как шестнадцатеричное от начала строки пока недопустимый символ как шестнадцатеричный.если
parseInt()
не удается найти число или букву как шестнадцатеричную в начале строкиparseInt()
вернутся Нэн.если радиус не определен, то он равен
10
.если строка начинается с
"0x"
, основание16
.если радиус определен
0
, основание10
.Если основание
1
,parseInt()
возврат NaN.Если основание
2
,parseInt()
только парсить"0"
и"1"
.Если основание
3
, parseInt() только парсить"0"
,"1"
и"2"
. И так далее.parseInt()
анализа"0"
до0
если нет номера следует за ним в результате и удалить0
если есть номер следовать ему. например," 0 "возвращает 0 и" 01 " возвращает 1.Если основание
11
,parseInt()
только строку разбора, который начинается с"0"
до"9"
и/или письмо"A"
.Если основание
12
, parseInt только парсить строку, которая начинается с"0"
до"9"
и/или письмо"A"
и"B"
и так далее.максимальный радиус
36
, он будет разбирать строку что начинается с"0"
до"9"
и/или"A"
to"Z"
.если символы интерпретируются как шестнадцатеричные более одного, каждый символ будет иметь разное значение, хотя эти символы являются одним и тем же символом. например,
parseInt("AA", 11)
первый"A"
имеет другое значение со вторым"A"
.другой radix вернет другой номер, хотя строки одинаковы строка.
посмотреть его в действии
document.body.innerHTML = "<b>What parseInt() does</b><br>" +
"parseInt('9') = " + parseInt('9') + "<br>" +
"parseInt('0129ABZ', 0) = " + parseInt('0129ABZ', 0) + "<br>" +
"parseInt('0', 1) = " + parseInt('0', 1) + "<br>" +
"parseInt('0', 2) = " + parseInt('0', 2) + "<br>" +
"parseInt('10', 2) = " + parseInt('10', 2) + "<br>" +
"parseInt('01', 2) = " + parseInt('01', 2) + "<br>" +
"parseInt('1', 2) = " + parseInt('1', 2) + "<br>" +
"parseInt('A', 10) = " + parseInt('A', 10) + "<br>" +
"parseInt('A', 11) = " + parseInt('A', 11) + "<br>" +
"parseInt('Z', 36) = " + parseInt('Z', 36) + "<br><br>" +
"<b>The value:</b><br>" +
"parseInt('A', 11) = " + parseInt('A', 11) + "<br>" +
"parseInt('A', 12) = " + parseInt('A', 12) + "<br>" +
"parseInt('A', 13) = " + parseInt('A', 13) + "<br>" +
"parseInt('AA', 11) = " + parseInt('AA', 11) + " = 100 + 20" + "<br>" +
"parseInt('AA', 12) = " + parseInt('AA', 12) + " = 100 + 30" + "<br>" +
"parseInt('AA', 13) = " + parseInt('AA', 13) + " = 100 + 40" + "<br>" +
"parseInt('AAA', 11) = " + parseInt('AAA', 11) + " = 1000 + 300 + 30" + "<br>" +
"parseInt('AAA', 12) = " + parseInt('AAA', 12) + " = 1000 + 500 + 70" + "<br>" +
"parseInt('AAA', 13) = " + parseInt('AAA', 13) + " = 1000 + 700 + 130" + "<br>" +
"parseInt('AAA', 14) = " + parseInt('AAA', 14) + " = 1000 + 900 + 210" + "<br>" +
"parseInt('AAA', 15) = " + parseInt('AAA', 15) + " = 1000 + 1100 + 310";
For radices above 10, the letters of the alphabet indicate numerals greater than 9. For example, for hexadecimal numbers (base 16), A through F are used.
в строке dsff66
, d
является шестнадцатеричным символом (даже если строка не является шестнадцатеричной), который соответствует типу radix и эквивалентен number 13
. После этого он перестает анализировать, так как следующий символ не является шестнадцатеричным, следовательно, результат.