Какой самый быстрый способ преобразовать строку в число в JavaScript?

122

Любой номер, это номер. Строка выглядит как число, это число. Все остальное - NaN.

'a' => NaN
'1' => 1
1 => 1
beatak
источник
Что является самым быстрым, зависит от оптимизаций в данной реализации в данный момент времени. Объективно «самого быстрого» способа не существует.
I Hate Lazy
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 отмечен как самый быстрый в 3 браузерах, но это затрудняет чтение кода… Так что выбирайте все, что вам нравится!

beatak
источник
7
Интересно, что Google Analytics (часть, которую вы вставляете на свой веб-сайт) использует 1*для преобразования даты в число, что аналогично приведенному +выше. т.е. 1*new Date()а не +new Date(). Может, читабельнее?
Мэтью Уилкоксон
1
Я думаю, что 1*это предпочтительнее, потому что он менее подвержен ошибкам. Нежелательная висящая ранее переменная +1не является ошибкой синтаксического анализа. Это уловка, аналогичная использованию if (MYCONSTANT == myvar)в C.
Tomas
5
@beatak - Текущая оптимизация, похоже, отдает предпочтение собственным методам, а не неявному преобразованию. Я получаю быстрее всего для Number () в Chrome 37.0.2062.124 в Windows Server 2008 R2 / 7 и ParseInt () в Firefox 30.0, причем неявное значение является самым медленным для обоих. Кроме того, вы можете рассмотреть возможность включения строковых литералов с плавающей запятой в тест для общего сравнения. Я предполагаю, что в некоторых случаях он может изменить порядок, потому что преобразование строки в float обычно медленнее, чем преобразование строки в int. В том виде, в каком сейчас проходит тест, при использовании Number () преобразование строки в int уходит.
Nolo
1
Хром 61.0.3163. Number () - самый быстрый из всех.
Дмитрий Петухов
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

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

перелив

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

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

Все зависит от того, как настроены тесты производительности, поскольку некоторые показывают, что parseInt / parseFloat намного медленнее.

Моя теория:

  • Вранье
  • Штрафные линии
  • Статистика
  • Результаты JSPerf :)
Исчезло кодирование
источник
3
Будьте очень осторожны с числами больше 2147483647. например: ~~4294967296возвращает 0.
Джозеф Го
@JosephGoh: Когда у меня будет возможность, я расширю результаты, включив переполнение диапазона int. Как правило, если числа такие большие, у вас есть особый интерфейс, поэтому вам нужно знать о переполнении. Cheers
Gone Coding
@JosephGoh: Интересно, что в Chrome вы не получаете 0, вы получаете отрицательные числа после максимального значения со знаком. Затем он просто отбрасывает лишние биты, когда вы превышаете значение unsigned int max. например, "4999999999" => 705032703
Gone Coding
8

Префикс строки с +оператором.

console.log(+'a') // NaN
console.log(+'1') // 1
console.log(+1) // 1
Pratheep
источник
7

Быстрый способ преобразовать строки в целое число - использовать побитовое или, например:

x | 0

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

user3784814
источник
Да, но я считаю, что этот метод усекает большие целые числа, что довольно плохо. Следует отметить, что меня также можно использовать вместо 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);
Эдмундо
источник
4

Я считаю, что num * 1это просто, понятно и работает для целых чисел и чисел с плавающей запятой ...

Дэниел Смит
источник
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
Домас
0

Вы можете попробовать использовать UnitOf , библиотеку измерений и преобразования типов данных, которую мы только что официально выпустили! UnitOf очень быстрый, маленький по размеру и эффективный при преобразовании любого типа данных без каких-либо ошибок или значений null / undefined. Значения по умолчанию, которые вы определяете, или значения по умолчанию 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.
Digidemic
источник
0

Самый быстрый способ - использовать -0:

const num = "12.34" - 0;
Артурас
источник