Я читаю це, але мене бентежить те, що написано в синтаксичному аналізі з розділом аргументу радіації
Чому parseInt(8, 3)
→ NaN
і parseInt(16, 3)
→ 1
?
AFAIK 8 і 16 не є базовими-3 числа, тому parseInt(16, 3)
повинні повернутися NaN
занадто
Я читаю це, але мене бентежить те, що написано в синтаксичному аналізі з розділом аргументу радіації
Чому parseInt(8, 3)
→ NaN
і parseInt(16, 3)
→ 1
?
AFAIK 8 і 16 не є базовими-3 числа, тому parseInt(16, 3)
повинні повернутися NaN
занадто
Відповіді:
Це те, що люди подорожують весь час, навіть коли про це знають. :-) Ви бачите це з тієї ж причини, що parseInt("1abc")
повертається 1: parseInt
зупиняється на першому недійсному символі та повертає все, що у нього є в цьому пункті. Якщо для розбору немає дійсних символів, він повертається NaN
.
parseInt(8, 3)
означає "розбір "8"
в базі 3" (зауважте, що він перетворює число 8
в рядок; деталі в специфікації ). Але в базі 3, однорозрядні числа просто 0
, 1
і 2
. Це як попросити його розібрати "9"
у восьмерику. Оскільки не було жодного дійсних символів, ви отримали NaN
.
parseInt(16, 3)
просить його проаналізувати "16"
в базі 3. Оскільки він може розібрати 1
, він робить, а потім зупиняється на 6
тому, що він не може його розібрати. Так воно повертається 1
.
Оскільки це питання привертає багато уваги і може зайняти високу позицію в результатах пошуку, ось перелік варіантів перетворення рядків у номери в JavaScript з їх різними ідіосинкратіями та програмами (знятий з іншої моєї відповіді тут на SO):
parseInt(str[, radix])
- Перетворює стільки, скільки може починати рядок, на ціле (ціле) число, ігноруючи зайві символи в кінці. Так parseInt("10x")
є 10
; x
ігнорується. Підтримує необов'язковий аргумент (база бази чисел), так parseInt("15", 16)
само 21
( 15
у шістнадцятковій формі ). Якщо немає радіусу, припускаємо десятковий, якщо рядок не починається з 0x
(або 0X
), у цьому випадку він пропускає їх і передбачає шістнадцятковий. (Деякі браузери, які використовуються для обробки рядків, починаючи з 0
восьмеричного; така поведінка ніколи не була вказана, і спеціально забороняється в специфікації ES5.) Повертається, NaN
якщо не знайдено розбірних цифр.
parseFloat(str)
- Як parseInt
, але чисел з плаваючою комою і підтримує лише десяткові. Знову зайві символи в рядку ігноруються, так parseFloat("10.5x")
є 10.5
( x
ігнорується). Оскільки підтримується лише десятковий знак, parseFloat("0x15")
є 0
(тому що розбір закінчується на x
). Повертається, NaN
якщо не знайдено аналогічних цифр.
Унарний +
, наприклад +str
- (Наприклад, неявна конверсія) Перетворює весь рядок у число за допомогою плаваючої точки та стандартного позначення номера JavaScript (просто цифри та десяткова крапка = десятковий; 0x
префікс = шестигранний; 0o
префікс = вісімковий [ES2015 +]; деякі реалізації розширюють його трактувати ведучого 0
як восьмеричний, але не в суворому режимі). +"10x"
це NaN
тому , що x
це НЕ ігнорується. +"10"
є 10
, +"10.5"
є 10.5
, +"0x15"
є 21
, +"0o10"
є 8
[ES2015 +]. Має gotcha: +""
є 0
, не так, NaN
як ви могли очікувати.
Number(str)
- Так само, як неявна конверсія (наприклад, як унарне +
вище), але повільніше в деяких реалізаціях. (Не те, що це, мабуть, має значення.)
parseInt
спочатку використовує toString
перший аргумент? Це мало б сенс.
parseInt
алгоритму: ecma-international.org/ecma-262/7.0/…
123e-2
дає, 1
оскільки він перетворюється 1.23
спочатку, а потім розбір зупиняється на десятковій точці?
NumberFormatException
кожен раз.
parseInt
(примушування першого аргументу до рядку) має сенс. Мета parseInt
- проаналізувати рядок на ціле число. Отже, якщо ви надаєте йому щось, що не є рядком, то, щоб почати строкове представлення цього тексту, має сенс Що після цього - це ціла «північна історія ...
З тієї ж причини, що
>> parseInt('1foobar',3)
<- 1
У допі , parseInt
приймає рядок. І
Якщо рядок не є рядком, він перетворюється на рядок
Отже 16
, 8
або '1foobar'
спочатку перетворюється на рядок.
Тоді
Якщо
parseInt
у вказаному радіусі зустрічається символ, який не є цифрою, він ігнорує його та всі наступні символи
Це означає, що він перетворює туди, куди може. І 6
, 8
і foobar
ігноруються, і конвертується лише те, що є раніше. Якщо нічого немає, NaN
повертається.
/***** Radix 3: Allowed numbers are [0,1,2] ********/
parseInt(4, 3); // NaN - We can't represent 4 using radix 3 [allowed - 0,1,2]
parseInt(3, 3); // NaN - We can't represent 3 using radix 3 [allowed - 0,1,2]
parseInt(2, 3); // 2 - yes we can !
parseInt(8, 3); // NaN - We can't represent 8 using radix 3 [allowed - 0,1,2]
parseInt(16, 3); // 1
//'16' => '1' (6 ignored because it not in [0,1,2])
/***** Radix 16: Allowed numbers/characters are [0-9,A-F] *****/
parseInt('FOX9', 16); // 15
//'FOX9' => 'F' => 15 (decimal value of 'F')
// all characters from 'O' to end will be ignored once it encounters the out of range'O'
// 'O' it is NOT in [0-9,A-F]
Ще кілька прикладів:
parseInt('45', 13); // 57
// both 4 and 5 are allowed in Radix is 13 [0-9,A-C]
parseInt('1011', 2); // 11 (decimal NOT binary)
parseInt(7,8); // 7
// '7' => 7 in radix 8 [0 - 7]
parseInt(786,8); // 7
// '78' => '7' => 7 (8 & next any numbers are ignored bcos 8 is NOT in [0-7])
parseInt(76,8); // 62
// Both 7 & 6 are allowed '76' base 8 decimal conversion is 62 base 10