Как преобразовать число с плавающей точкой в ​​целое число в JavaScript?

1110

Я хотел бы преобразовать число с плавающей точкой в ​​JavaScript. На самом деле, я хотел бы знать, как сделать ОБА из стандартных преобразований: путем усечения и округления. И эффективно, а не путем преобразования в строку и анализа.

mcherm
источник
83
Если вы этого не знали, все числа в JavaScript являются числами с плавающей точкой. Из спецификации:
около
6
4.3.20 Тип номера: Тип Номер - это набор значений, представляющих числа. В ECMAScript набор значений представляет значения IEEE 754 в 64-битном формате двойной точности, включая специальные значения «Not-a-Number» (NaN), положительную бесконечность и отрицательную бесконечность.
некоторые
9
Да, Javascript не имеет определенного «целочисленного» типа, но все же нередко нужно делать это преобразование. Например, в моем приложении пользователи вводили число (возможно, включая центы). Пришлось обрезать центы и показывать запятые. Шаг 1 должен был преобразовать в int.
mcherm
1
Также полезно: сравнение скорости всех методов jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..
1
@karl: Если я принимаю ввод в поле, я мог бы контролировать, какие символы я принимаю, но я мог выполнять все виды обработки в Javascript, а не только принимать пользовательский ввод. Даже тогда я мог бы хотеть это для вещей как поддержка пасты.
mcherm

Ответы:

1609
var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue ); 
var intvalue = Math.round( floatvalue );

// `Math.trunc` was added in ECMAScript 6
var intvalue = Math.trunc( floatvalue );

Ссылка на объект Math


Примеры

положительный
// value=x        //  x=5          5<x<5.5      5.5<=x<6  

Math.floor(value) //  5            5            5
Math.ceil(value)  //  5            6            6
Math.round(value) //  5            5            6
Math.trunc(value) //  5            5            5
parseInt(value)   //  5            5            5
~~value           //  5            5            5
value | 0         //  5            5            5
value >> 0        //  5            5            5
value >>> 0       //  5            5            5
value - value % 1 //  5            5            5
отрицательный
// value=x        // x=-5         -5>x>=-5.5   -5.5>x>-6

Math.floor(value) // -5           -6           -6
Math.ceil(value)  // -5           -5           -5
Math.round(value) // -5           -5           -6
Math.trunc(value) // -5           -5           -5
parseInt(value)   // -5           -5           -5
value | 0         // -5           -5           -5
~~value           // -5           -5           -5
value >> 0        // -5           -5           -5
value >>> 0       // 4294967291   4294967291   4294967291
value - value % 1 // -5           -5           -5
Положительный - Большие числа
// x = Number.MAX_SAFE_INTEGER/10 // =900719925474099.1

// value=x            x=900719925474099    x=900719925474099.4  x=900719925474099.5

Math.floor(value) //  900719925474099      900719925474099      900719925474099
Math.ceil(value)  //  900719925474099      900719925474100      900719925474100
Math.round(value) //  900719925474099      900719925474099      900719925474100
Math.trunc(value) //  900719925474099      900719925474099      900719925474099
parseInt(value)   //  900719925474099      900719925474099      900719925474099
value | 0         //  858993459            858993459            858993459
~~value           //  858993459            858993459            858993459
value >> 0        //  858993459            858993459            858993459
value >>> 0       //  858993459            858993459            858993459
value - value % 1 //  900719925474099      900719925474099      900719925474099
Отрицательный - Большие числа
// x = Number.MAX_SAFE_INTEGER/10 * -1 // -900719925474099.1

// value = x      // x=-900719925474099   x=-900719925474099.5 x=-900719925474099.6

Math.floor(value) // -900719925474099     -900719925474100     -900719925474100
Math.ceil(value)  // -900719925474099     -900719925474099     -900719925474099
Math.round(value) // -900719925474099     -900719925474099     -900719925474100
Math.trunc(value) // -900719925474099     -900719925474099     -900719925474099
parseInt(value)   // -900719925474099     -900719925474099     -900719925474099
value | 0         // -858993459           -858993459           -858993459
~~value           // -858993459           -858993459           -858993459
value >> 0        // -858993459           -858993459           -858993459
value >>> 0       //  3435973837           3435973837           3435973837
value - value % 1 // -900719925474099     -900719925474099     -900719925474099
Лунная тень
источник
82
Как уже упоминалось в другом ответе, можно использовать отрицательно-безопасное усечение var intValue = ~~floatValue;. Если запись слишком затемнять для ваших вкусов, просто скрыть его в функции: function toInt(value) { return ~~value; }. (Это также преобразует строки в целые числа, если вы хотите это сделать.)
Keen
4
Было бы upvote, если этот ответ имеет пример ввода / вывода.
случайный кодер J.
7
Что касается комментария, ~~ ограничивает значение 32-разрядными знаковыми целыми числами, в то время как Math.floor / ceil / round может обрабатывать до 53-разрядных (Number.MAX_SAFE_INTEGER 9007199254740991). Это упоминается в ответе ниже, но стоит повторить здесь для тех, кто читает эти комментарии.
Джон
2
Читайте снизу в нескольких местах: Math.trunc(val);Комментируйте, потому что это принятый ответ
Старый Badman Grey
Не работает с точной точностью для таких значений, как2.3 - 2.3 % 1
Lapys
301

Побитовый оператор ИЛИ

Побитовый или оператор можно использовать для усечения чисел с плавающей запятой, и он работает как для положительных, так и для отрицательных значений:

function float2int (value) {
    return value | 0;
}

Результаты

float2int(3.1) == 3
float2int(-3.1) == -3
float2int(3.9) == 3
float2int(-3.9) == -3

Сравнение производительности?

Я создал тест JSPerf, который сравнивает производительность между:

  • Math.floor(val)
  • val | 0 побитовое ИЛИ
  • ~~val поразрядно НЕ
  • parseInt(val)

это работает только с положительными числами. В этом случае вы можете безопасно использовать побитовые операции как Math.floorфункции.

Но если вам нужен код для работы как с положительными, так и с отрицательными значениями , побитовая операция является самой быстрой (ИЛИ предпочтительной). Этот другой тест JSPerf сравнивает то же самое, где совершенно очевидно, что из-за дополнительной проверки знака Math теперь самый медленный из четырех.

Запись

Как указано в комментариях, операторы BITWISE работают с 32-разрядными целыми числами со знаком, поэтому большие числа будут преобразованы, например:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987
Роберт Коритник
источник
@FabioPoloni: да, супер просто и кажется, что побитовые операторы самые быстрые. В особенности оператор OR всегда самый быстрый, часто совпадающий с операциями NOT и Math, хотя математические операции являются самыми медленными, когда вам нужно также поддерживать отрицательные числа, потому что он добавляет дополнительную проверку знака числа.
Роберт Коритник
9
@thefourtheye: Все побитовые операции, кроме беззнакового сдвига вправо, работают с 32-разрядными целыми числами со знаком. Поэтому использование побитовых операций со значениями с плавающей запятой преобразует их в целое число, убирающее цифры после десятичной точки.
Роберт Коритник
3
Если вам просто нужно это для положительных чисел, Math.floor()это быстрее (по крайней мере, в соответствии с моим выполнением вашего первого теста JSPerf в Google Chrome, версия 30.0.1599.101), более надежным (потому что это не зависит от того, как числа представлены в битах, что может изменить и, возможно, нарушить это побитовое решение), а главное, более явным.
ma11hew28
8
Обратите внимание, что побитовые операторы работают с 32-битными числами. Они не будут работать для чисел, слишком больших, чтобы поместиться в 32 бит.
Кат
2
~~лучше, потому что это унарный оператор. 4.2|0+4равно, 4но ~~4.2+4равно8
Янус Троелсен
94

Примечание: вы не можете использовать Math.floor()в качестве замены для усечения, потому что Math.floor(-3.1) = -4и не-3 !!

Правильная замена для усечения будет:

function truncate(value)
{
    if (value < 0) {
        return Math.ceil(value);
    }

    return Math.floor(value);
}
Джексон
источник
1
Это зависит от желаемого поведения для отрицательных чисел. Некоторым пользователям нужны отрицательные числа для отображения на более отрицательное значение (-3,5 -> -4), а некоторым требуется, чтобы они отображались на меньшее целое число (-3,5 -> -3). Первый обычно называется «пол». Слово «усекать» часто используется для описания любого поведения. В моем случае я собирался кормить его только отрицательными числами. Но этот комментарий является полезным предупреждением для тех, кому действительно небезразлично поведение отрицательных чисел.
mcherm
28
@mcherm: Тогда они, похоже, неправильно понимают термин «усекать». Truncate делает именно так, как следует из его названия: он усекает цифры. Это никогда (в общем смысле) не эквивалентно полу или потолку. en.wikipedia.org/wiki/Truncation
Танатос,
5
Math.trunc(value)был добавлен в ECMAScript 6
4esn0k
2
floorокругляет до бесконечности, truncateокругляет до нуля. ( ceilокругляется до + бесконечности).
Питер Кордес
46

Двойной побитовый оператор not можно использовать для усечения чисел с плавающей запятой. Другие операции , упомянутые вами доступны через Math.floor, Math.ceilи Math.round.

> ~~2.5
2
> ~~(-1.4)
-1

Больше деталей любезно предоставлено Джеймсом Падолси.

штифтик
источник
1
Это, вероятно, плохая вещь для производственного кода (поскольку он неясен), но это было именно то, что мне нужно для игры в код моего <canvas>движка рендеринга шрифтов в JS . Спасибо!
Краген Хавьер Ситакер
10
Это также можно сделать с помощью n | 0.
Джей Дуглас
17
Обратите внимание, что любой метод (~~ n или n | 0) работает только с числами до 2 ^ 31-1 или 2147483647. 2147483648 или выше вернет неверный результат; например, 2147483647 | 0 возвращает -2147483648, а 4294967295 | 0 возвращает -1, что почти наверняка не то, что вы хотите.
Эд Байятес,
40

Для усечения:

var intvalue = Math.floor(value);

Для тура:

var intvalue = Math.round(value);
Майк
источник
6
Math.floor не усекает отрицательные значения. Смотрите ответ выше. В противном случае хороший ответ.
oligofren
Если вы заинтересованы в производительности, я поставил небольшой тестовый пример: jsperf.com/dsafdgdfsaf/2 ( здесь выигрывает var | 0).
Cybolic
25

Вы можете использовать метод parseInt без округления. Будьте осторожны с пользовательским вводом из-за вариантов префикса 0x (шестнадцатеричный) и 0 (восьмеричный).

var intValue = parseInt(floatValue, 10);
Грэм Викстед
источник
1
Это на самом деле полезно, когда вам просто нужна целая часть десятичной дроби, без округления вверх или вниз, что и делают .round, .ceil и .floor.
Иуда Габриэль Химанго
1
... даже при простом усечении это кажется самым медленным методом. jsperf.com/float-to-int-conversion-comparison
Роберт Коритник
2
Всегда передавайте 2-е значение parseInt, чтобы указать, какую базу вы ожидаете. Таким образом, parseInt (floatValue, 10) всегда получает базу 10.
Тим Тисдалл
3
Хотя это старый вопрос, этот вопрос, похоже, часто задают, поэтому я поставлю его здесь как предупреждение. Если значение будет представлено с использованием нотации «e» из-за его размера, оно просто приведет к одной цифре, а не к тому, что ожидается. Например, parseInt(1000000000000000000000, 10);результат 1, а не 1 000 000 000 000 000 000 000. Во всяком случае, вопрос явно не хотел " преобразования в строку и синтаксический анализ ", хотя это относительно незначительно ...;)
Qantas 94 Heavy
4
@ Qantas94Heavy Причина такого поведения, потому что parseInt()ожидает строку, а не число в качестве первого параметра. Когда вы передаете это целое число, оно преобразуется в 1e21и затем parseIntанализирует строку 1e21, что приводит к 1.
Олаф Дитче
18

Сдвиг битов на 0, что эквивалентно делению на 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2
Prasanth
источник
4
Небольшое примечание: >> 0кажется, работает только для целых чисел < 2 ^ 31-1 , и >>> 0для целых чисел < 2 ^ 32-1 . Это возвращает 0 для больших значений
Romuald Brunet
@RomualdBrunet, да, JavaScript четко определяет все побитовые операции как работающие с 32-битными числами. Это в спецификации.
Алексис Вилке
Это работает, поскольку Javascript выполняет побитовые операции только с 32-битными (знаковыми) целыми числами, как указано в ответе выше. Таким образом, любая битовая операция, которая, кажется, ничего не делает (например, сдвиг для 0, ИЛИ с 0, И с 1, двойное НЕ), все еще нуждается в интерпретаторе Javascript для преобразования значения в 32-битное int.
FrankKrumnow
9

В вашем случае, когда вам нужна строка в конце (для вставки запятых), вы также можете просто использовать Number.toFixed()функцию, однако она выполнит округление.

Рассел Леггетт
источник
7

Здесь много предложений. Побитовое ИЛИ кажется самым простым на сегодняшний день. Вот еще одно короткое решение, которое работает и с отрицательными числами, используя оператор по модулю. Это, вероятно, легче понять, чем побитовое ИЛИ:

intval = floatval - floatval%1;

Этот метод также работает с большими значениями, где ни «| 0», ни «~~», ни «>> 0» не работают правильно:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295
Джулиана Хольцт
источник
Если вы ссылаетесь на другой ответ, пожалуйста, добавьте ссылку на него или кратко набросайте его идею.
Бертл
5

Чтобы усечь :

// Math.trunc() is part of the ES6 spec
Math.trunc( 1.5 );  // returns 1
Math.trunc( -1.5 ); // returns -1
// Math.floor( -1.5 ) would return -2, which is probably not what you wanted

Для округления :

Math.round( 1.5 );  // 2
Math.round( 1.49 ); // 1
Math.round( -1.6 ); // -2
Math.round( -1.3 ); // -1
бритва
источник
5

Еще один возможный способ - использовать операцию XOR:

console.log(12.3 ^ 0); // 12
console.log("12.3" ^ 0); // 12
console.log(1.2 + 1.3 ^ 0); // 2
console.log(1.2 + 1.3 * 2 ^ 0); // 3
console.log(-1.2 ^ 0); // -1
console.log(-1.2 + 1 ^ 0); // 0
console.log(-1.2 - 1.3 ^ 0); // -2

Приоритет побитовых операций меньше, чем приоритет математических операций, это полезно. Попробуйте на https://jsfiddle.net/au51uj3r/

Дмитрий Харитонов
источник
2

Если вы посмотрите на нативный Mathобъект в JavaScript, вы получите целый набор функций для работы с числами и значениями и т. Д.

В основном то, что вы хотите сделать, довольно просто и встроено в JavaScript ...

Представьте, что у вас есть номер ниже:

const myValue = 56.4534931;

и теперь, если вы хотите округлить его до ближайшего числа, просто сделайте:

const rounded = Math.floor(myValue);

и вы получите:

56

Если вы хотите округлить его до ближайшего числа, просто выполните:

const roundedUp = Math.ceil(myValue);

и вы получите:

57

Кроме Math.roundтого, округление до большего или меньшего числа зависит от того, какой из них ближе к числу смещения.

Также вы можете использовать число ~~с плавающей точкой, которое преобразует число с плавающей точкой в ​​целое число.

Вы можете использовать его как ~~myValue...

Алиреза
источник
Будьте осторожны с тем, ~~что если число больше предела int 32, оно изменит значение на предельное значение int 32.
Мачадо
1

//Convert a float to integer

Math.floor(5.95)
//5

Math.ceil(5.95)
//6

Math.round(5.4)
//5

Math.round(5.5)
//6

Math.trunc(5.5)
//5

//Quick Ways
console.log(5.95| 0)
console.log(~~5.95) 
console.log(5.95 >> 0)
//5

pk_code
источник
0

Я просто хочу указать, что в денежном выражении вы хотите округлить, а не усечь. Снижение на пенни гораздо менее вероятно, так как округленное 4.999452 * 100 даст вам 5, более представительный ответ.

И, кроме того, не забывайте о банковском округлении , которое является способом противостоять слегка положительному смещению, которое дает прямое округление - вашему финансовому заявлению это может потребоваться.

Гауссово / банковское округление в JavaScript

Жерар ОНЕЙЛ
источник
0

Если вы используете angularjs, тогда простое решение:

{{val | number:0}}

преобразует val в целое число

перейдите по этой ссылке docs.angularjs.org/api/ng/filter/number

Джамиль Гранд
источник