Який найшвидший спосіб перетворити рядок у номер у JavaScript?


122

Будь-яке число, це число. Рядок схожий на число, це число. Все інше, це йде NaN.

'a' => NaN
'1' => 1
1 => 1

Що найшвидше, це залежить від оптимізацій в даній реалізації в даний момент часу. Об'єктивно "найшвидшого" способу немає.
Я ненавиджу ледачий

2
Що робити з '1a'рядком? З ' 1'одним? Іншими словами, чому найбільш поширених методів зробити це ( Number(x)і parseInt(x, 10)) вам недостатньо?
raina77ow

Попередній тест на jsperf: jsperf.com/converting-string-to-int/3
epascarello

тут хороше порівняння ефективності різних методів: jsben.ch/#/NnBKM
EscapeNetscape

Відповіді:


192

Наскільки я знаю, це 4 способи зробити це.

Number(x);
parseInt(x, 10);
parseFloat(x);
+x;

Цей швидкий тест, який я зробив, він фактично залежить від браузерів.

http://jsperf.com/best-of-string-to-number-conversion/2

Implicit позначено найшвидшим у трьох веб-переглядачах, але це робить код важким для читання… Тож вибирайте все, що вам заманеться!


7
Цікаво, що Google Analytics (частина, яку ви вставляєте на свій веб-сайт) використовує 1*для перетворення дат до числа, що аналогічно +вище. тобто, 1*new Date()а не +new Date(). Можливо, це читабельніше?
Меттью Вілкокссон

1
Я думаю 1*, що кращим, тому що він менш схильний до помилок. Небажана звисаюча змінна раніше +1- не помилка розбору. Це трюк, подібний до використання if (MYCONSTANT == myvar)в C.
Томаш

5
@beatak - Здається, що поточні оптимізації віддають перевагу нативним методам на відміну від неявного перетворення. Я найшвидший за номер () у Chrome 37.0.2062.124 на Windows Server 2008 R2 / 7 та ParseInt () у Firefox 30.0, причому неявна є найбільш повільною для обох. Крім того, ви можете розглянути можливість включення рядкових буквальних плавців у тест для загального порівняння. Я здогадуюсь, що це може змінити порядок у деяких випадках, оскільки перетворення рядка на плаваючу частину, як правило, повільніше, ніж перетворення на рядок до int. Тест, який зараз тестує, він починає переходити рядок до int перетворення, коли використовується Number ().
Ноло

1
Chrome 61.0.3163. Число () найшвидше з усіх.
Дмитро Петухов

70

Існує щонайменше 5 способів зробити це:

Якщо ви хочете конвертувати лише цілі числа, ще одним швидким (і коротким) способом є подвійне розрядне значення (тобто використання двох символів тильди):

напр

~~x;

Довідка: http://james.padolsey.com/cool-stuff/double-bitwise-not/

У 5 поширених мені способів перетворення рядка в число всі мають свої відмінності (є більш бітові оператори, які працюють, але всі вони дають той же результат, що і ~~ ). Цей JSFiddle показує різні результати, які можна очікувати на консолі налагодження: http://jsfiddle.net/TrueBlueAussie/j7x0q0e3/22/

var values = ["123",
          undefined,
          "not a number",
          "123.45",
          "1234 error",
          "2147483648",
          "4999999999"
          ];

for (var i = 0; i < values.length; i++){
    var x = values[i];

    console.log(x);
    console.log(" Number(x) = " + Number(x));
    console.log(" parseInt(x, 10) = " + parseInt(x, 10));
    console.log(" parseFloat(x) = " + parseFloat(x));
    console.log(" +x = " + +x);
    console.log(" ~~x = " + ~~x);
}

Консоль налагодження:

123
  Number(x) = 123
  parseInt(x, 10) = 123
  parseFloat(x) = 123
  +x = 123
  ~~x = 123
undefined
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
null
  Number(x) = 0
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = 0
  ~~x = 0
"not a number"
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
123.45
  Number(x) = 123.45
  parseInt(x, 10) = 123
  parseFloat(x) = 123.45
  +x = 123.45
  ~~x = 123
1234 error
  Number(x) = NaN
  parseInt(x, 10) = 1234
  parseFloat(x) = 1234
  +x = NaN
  ~~x = 0
2147483648
  Number(x) = 2147483648
  parseInt(x, 10) = 2147483648
  parseFloat(x) = 2147483648
  +x = 2147483648
  ~~x = -2147483648
4999999999
  Number(x) = 4999999999
  parseInt(x, 10) = 4999999999
  parseFloat(x) = 4999999999
  +x = 4999999999
  ~~x = 705032703

The ~~x результатах версії в ряді в «більш» випадках, коли інші часто призводять undefined, але він не для неприпустимого введення (наприклад , він повернеться , 0якщо рядок містить не число символів після того, як дійсне числа).

Переповнення

Зверніть увагу: може виникати переповнення цілого чи / або бітового скорочення ~~, але не з іншими перетвореннями. Хоча введення таких великих значень незвично, вам потрібно знати про це. Приклад оновлено, щоб включити набагато більші значення.

Деякі тести Perf вказують, що стандарт parseIntі parseFloatфункції - це фактично найшвидші варіанти, імовірно, оптимізовані браузерами, але все залежить від вашої вимоги, оскільки всі параметри досить швидкі : http://jsperf.com/best-of-string-to -число перетворення / 37

Все це залежить від того, як налаштовані тести perf, оскільки деякі показують parseInt / parseFloat набагато повільніше.

Моя теорія:

  • Брехня
  • Чортові лінії
  • Статистика
  • Результати JSPerf :)

3
Будьте дуже обережні щодо чисел, більших за 2147483647. Наприклад: ~~4294967296повертає 0.
Джозеф Гох

@JosephGoh: Коли я отримаю можливість, я розширю результати, щоб включити переповнення діапазону int. Як правило, якщо величини такі великі, у вас є дуже особливий інтерфейс, тому потрібно мати на увазі переповнення. Ура
Кодування пішло

@JosephGoh: Цікаво, що в Chrome ви не отримуєте 0, ви отримуєте від’ємні цифри понад підписане максимальне значення. Тоді, як видається, просто випадають зайві біти, коли ви перевищуєте непідписане int max значення. напр., "4999999999" => 705032703
кодування

8

Префікс рядка з +оператором.

console.log(+'a') // NaN
console.log(+'1') // 1
console.log(+1) // 1

7

Швидкий спосіб перетворення рядків у ціле число - це використання побітових або так:

x | 0

Хоча це залежить від того, як вона реалізована, теоретично вона повинна бути відносно швидкою (принаймні такою ж швидкою, як +x), оскільки спочатку вона буде передаватися xна число, а потім виконувати дуже ефективно або.


Так, але я вважаю, що ця техніка обрізає великі цілі числа, це дуже погано. Зауважимо, що я також можу використовуватись замість Math.floor (), але з тим же питанням.
Жан

Ось jsperf різних побітових операторів у поєднанні з методами у першій відповіді. Я рандомізував замовлення, оскільки виявив, що деякі браузери оптимізують наступний тест на основі аналогічного коду з попереднього тесту. На відміну від найвищого відповідача, я виявив, що неявний метод був найгіршим.
Плутон

4

Ось простий спосіб зробити це: var num = Number (str); у цьому прикладі str - це змінна, що містить рядок. Ви можете протестувати і подивитися, як це працює відкрито: інструменти для розробників Google Chrome , потім перейдіть до консолі та вставте наступний код. прочитайте коментарі, щоб краще зрозуміти, як здійснюється конверсія.

// Here Im creating my variable as a string
var str = "258";


// here im printing the string variable: str
console.log ( str );


// here Im using typeof , this tells me that the variable str is the type: string
console.log ("The variable str is type: " + typeof str);


// here is where the conversion happens
// Number will take the string in the parentesis and transform it to a variable num as type: number
var num = Number(str);
console.log ("The variable num is type: " + typeof num);


3

Це, мабуть, не так швидко, але має додаткову перевагу - переконайтеся, що ваш номер є хоча б певним значенням (наприклад, 0), або щонайменше певним значенням:

Math.max(input, 0);

Якщо вам потрібно забезпечити мінімальне значення, зазвичай це зробити

var number = Number(input);
if (number < 0) number = 0;

Math.max(..., 0) рятує вас від написання двох заяв.


Чому б не використовувати Math.abs(input)? Він також перетворює рядки в додатні числа і зберігає кілька зайвих символів.
Аарон Гліон

1
@AaronGillion: Math.max (-5, 0) поверне 0; Math.abs (-5) повернеться 5. Це залежить від випадку використання, який має більше сенсу.
Дан Даскалеску

1
О, так, так, мій випадок використання був різним, коли я пізно вночі писав цей коментар.
Аарон Гліон

Якщо inputне вдасться перетворити на номер, ви отримаєтеNaN
Domas

0

Ви можете спробувати використати UnitOf , бібліотеку вимірювання та перетворення типів даних, яку ми офіційно випустили! UnitOf - це супершвидкий, невеликий розмір і ефективний при перетворенні будь-якого типу даних, не викидаючи жодної помилки чи нульової / невизначеної. Значення за замовчуванням, які ви визначаєте, або за замовчуванням UnitOf повертаються, коли перетворення не вдалося.

//One liner examples
UnitOf.DataType("12.5").toFloat(); //12.5 of type Float is returned. 0 would be returned if conversion failed.
UnitOf.DataType("Not A Num").toInt(10); //10 of type Int is returned as the conversion failed.

//Or as a variable
var unit = UnitOf.DataType("12.5");
unit.toInt(5); //12.5 of type Float is returned. 5 would be returned if the conversion failed.
unit.toFloat(8); // 12 of type Int is returned. 8 would be returned if the conversion failed.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.