Почему 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. После этого он перестает анализировать, так как следующий символ не является шестнадцатеричным, следовательно, результат.