Як перетворити число з плавкою на ціле число в JavaScript?


1108

Я хотів би перетворити float на ціле число в JavaScript. Насправді, я хотів би знати, як зробити БОТУ стандартних перетворень: обрізанням і округленням. І ефективно, не перетворюючи на рядок і розбираючи.


83
Якщо ви цього не знали, усі числа у javascript є плаваючими. З специфікації:
якийсь

6
4.3.20 Тип номера: Тип Число - це набір значень, що представляють числа. У ECMAScript набір значень представляє 64-бітний формат IEEE 754 подвійної точності, включаючи спеціальні значення "Не-Число" (NaN), позитивну нескінченність та негативну нескінченність.
десь

9
Так, у Javascript немає чіткого "цілого" типу, але все ще не рідкість потрібно робити це перетворення. Наприклад, у моїй програмі користувачі набрали число (можливо, включаючи центи). Мені довелося врізати центи і відображати w / коми. Крок 1 полягав у перетворенні на int.
mcherm

1
також корисно: порівняння швидкості всіх методів jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..

1
@karl: Якщо я приймаю введення в поле, я можу контролювати, які символи я приймаю, але я можу робити всі види обробки в Javascript, а не просто приймати введення користувача. Навіть тоді я, можливо, захочу це за такі речі, як підтримуюча паста.
mcherm

Відповіді:


1608
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 );

Посилання на математичний об'єкт


Приклади

Позитивний
// 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; }. (Це також перетворює рядки в цілі числа, якщо ви це робите.)
Кін

4
Підтверджує, якби ця відповідь мала приклад введення / виводу.
J. Random Coder

7
Щодо коментаря ~~ обмежує значення на 32 бітові цілі числа, а Math.floor / ceil / round може обробляти до 53-бітових (Number.MAX_SAFE_INTEGER 9007199254740991). Про це йдеться у відповіді нижче, але варто повторити тут тих, хто читає ці коментарі.
Іван,

2
Читайте знизу в декількох місцях: Math.trunc(val);Прокоментуйте, оскільки це прийнята відповідь
Старий Бадман Грей

Не працює з точною точністю для таких значень, як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: так супер просто, і здається, що бітові оператори є найшвидшими. Особливо оператор АБО завжди найшвидший, що часто відповідає НЕ та операціям з математикою, хоча операції з математикою є найбільш повільними, коли вам також потрібно підтримувати від’ємні числа, оскільки він додає додаткову перевірку знаку числа.
Роберт Коритник

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: Тоді вони, мабуть, не розуміють правильно термін "усікати". Урізання виконує саме так, як випливає з назви: він урізує цифри. Він ніколи (в загальному сенсі) не еквівалентний підлозі чи стелі. en.wikipedia.org/wiki/Трункація
Танатос

5
Math.trunc(value)додано в ECMAScript 6
4esn0k

2
floorкруги у бік нескінченності, truncateкруги до нуля. ( ceilкругляє до + нескінченності).
Пітер Кордес

46

Оператор з подвійним розрядом не може використовуватися для обрізання плавців. Інші операції , згадані вами доступні через 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 не скорочує негативні значення. Дивіться відповідь вище. Інакше приємна відповідь.
олігофрен

Якщо вас цікавить продуктивність, я поставив тут невеликий тестовий випадок: 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-comparing
Роберт Коритник

2
Завжди передайте 2-е значення 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

4
Мала примітка: >> 0начебто, працює лише для цілих чисел < 2 ^ 31-1 , а >>> 0для цілих чисел < 2 ^ 32-1 . Це повертає 0 для більших значень
Ромуальд Брюне

@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

Якщо ви посилаєтесь на іншу відповідь, будь-ласка, додайте до неї посилання або коротко прорисуйте її ідею.
bertl

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просто округлення його до більшого або нижчого числа залежить від того, який з них ближче до числа флота.

Також ви можете використовувати ~~поза числом float, яке перетворить поплавок на ціле число.

Ви можете використовувати його як ~~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


0

Я просто хочу зазначити, що грошово ви хочете округлити, а не обрізати. Відмовитися від копійки набагато менш вірогідно, оскільки 4.999452 * 100 в округленні дасть вам 5, більш представницьку відповідь.

На додаток до цього не забувайте про округлення банкіра , який є способом протистояти злегка позитивним ухилам, які дає пряме округлення - ваша фінансова заявка може цього вимагати.

Округлення Гаусса / банкіра в JavaScript


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