1508

I'd like to convert a float to a whole number in JavaScript. Actually, I'd like to know how to do BOTH of the standard conversions: by truncating and by rounding. And efficiently, not via converting to a string and parsing.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mcherm
  • 23,999
  • 10
  • 44
  • 50
  • 102
    If you didn't know it, all numbers in javascript are floats. From the specification: – some Feb 28 '09 at 02:40
  • 8
    4.3.20 Number Type: The type Number is a set of values representing numbers. In ECMAScript, the set of values represents the doubleprecision 64-bit format IEEE 754 values including the special “Not-a-Number” (NaN) values, positive infinity, and negative infinity. – some Feb 28 '09 at 02:41
  • 12
    Yes, Javascript does not have a distinct "integer" type, but it is still not uncommon to need to do this conversion. For instance, in my application users typed in a number (possibly including cents). I had to truncate the cents and display w/ commas. Step 1 was to convert to int. – mcherm Feb 28 '09 at 15:40
  • 1
    also useful: speed comparison of all methods http://jsperf.com/math-floor-vs-math-round-vs-parseint/33 – c.. Jul 26 '12 at 18:10
  • @mcherm why not trap for the decimal character and not allow it's use? Doesn't that make for a better user experience? Additionally, if your code only permits the user to enter [0..9] then you don't have to convert to an integer. Still a useful question. – Karl Oct 28 '12 at 22:54
  • 1
    @karl: If I'm accepting input into a field, I might be able to control what characters I accept, but I could be doing all kinds of processing in Javascript, not just accepting user input. Even then I might want it for things like supporting paste. – mcherm Oct 30 '12 at 16:55

18 Answers18

2165
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 object reference


Examples

Positive
// 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
Negative
// 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
Positive - Larger numbers
// 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
Negative - Larger numbers
// 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
Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
moonshadow
  • 86,889
  • 7
  • 82
  • 122
  • 90
    As mentioned in another answer, a negative-safe truncate can be done using `var intValue = ~~floatValue;`. If the notation is too obscure for your tastes, just hide it in a function: `function toInt(value) { return ~~value; }`. (This also converts strings to integers, if you care to do so.) – Keen Apr 19 '13 at 19:08
  • 6
    Would upvote if this answer had example input/output. – J. Random Coder Aug 27 '15 at 14:40
  • 11
    Regarding the comment ~~ limits the value to 32 bit signed integers, while Math.floor/ceil/round can handle up to 53-bit (Number.MAX_SAFE_INTEGER 9007199254740991). This is mentioned in the answer below, but it is worth repeating here for those reading these comments. – John Mar 28 '16 at 15:27
  • 3
    Read from below in several places: `Math.trunc(val);` Comment because this is the accepted answer – Old Badman Grey May 05 '16 at 06:05
  • 1
    Does not work with exact precision for values like `2.3 - 2.3 % 1` – Lapys Nov 06 '18 at 23:31
341

Bitwise OR operator

A bitwise or operator can be used to truncate floating point figures and it works for positives as well as negatives:

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

Results

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

Performance comparison?

I've created a JSPerf test that compares performance between:

  • Math.floor(val)
  • val | 0 bitwise OR
  • ~~val bitwise NOT
  • parseInt(val)

that only works with positive numbers. In this case you're safe to use bitwise operations well as Math.floor function.

But if you need your code to work with positives as well as negatives, then a bitwise operation is the fastest (OR being the preferred one). This other JSPerf test compares the same where it's pretty obvious that because of the additional sign checking Math is now the slowest of the four.

Note

As stated in comments, BITWISE operators operate on signed 32bit integers, therefore large numbers will be converted, example:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987
Nick.T
  • 587
  • 4
  • 20
Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • @FabioPoloni: yes super simple and seems that bitwise operators are the fastest. Especially the OR operator is always the fastest often matched by NOT and Math operations although Math operations are the slowest when you have to support negative numbers as well, because it adds an additional check of number sign. – Robert Koritnik Jan 10 '13 at 13:54
  • 11
    @thefourtheye: All bitwise operations except unsigned right shift, work on signed 32-bit integers. Therefore using bitwise operations on floating point values will convert them to an integer stripping off digits after decimal point. – Robert Koritnik Sep 02 '13 at 12:22
  • bitwise Not is powerfull in terms of speed. – Murtaza Khursheed Hussain Sep 18 '13 at 12:59
  • Aside ... Logically, bitwise AND, OR, XOR, and shift operations extend naturally to floating-point -- align operands on their binary points then operate. For example, 0.375 & 0.750 = 0.25 (0.110b & 0.011b = 0.010b). Bitwise NOT is trickier -- it becomes almost negate, e.g., ~1.0b = ...1110.1111... ~= -1.0b. – Peter Raynham Oct 13 '13 at 22:46
  • 4
    If you just need it for positive numbers, `Math.floor()` is faster (at least according to my running of your first [JSPerf test](http://jsperf.com/float-to-int-conversion-comparison) on Google Chrome, version 30.0.1599.101), more robust (because it doesn't depend on how numbers are represented in bits, which may change and possibly break this bitwise solution), and most importantly, more explicit. – ma11hew28 Oct 19 '13 at 16:29
  • 9
    Note that the bitwise operators operate on 32 bit numbers. They won't work for numbers too large to fit in 32 bits. – Kat Oct 31 '13 at 00:09
  • 2
    `~~` is better because it's a unary operator. `4.2|0+4` equals `4` but `~~4.2+4` equals `8` – Janus Troelsen Jan 13 '15 at 18:10
  • Current testing in Mac OSX 10.10: FF38 (`|0` fastest, `~~` and `Math.floor` tied at 46% slower than `|0`), Chrome43 (`|0`, `~~`, and `Math.floor` statistically tied), Safari8.0 (`|0` and `~~` statistically tied for fastest, `Math.floor` is 95% slower). At least on a Mac, `|0` is the fastest, with `~~` the next best by speed. – Pi Marillion Jun 10 '15 at 14:00
  • Thanks for the complete answer with testing! However, even if `bitwise or` runs a hair faster than `Math.floor()`, I think the math function is less cryptic, even to seasoned JavaScript programmers, so I would suggest using `Math.floor()`. – Chunky Chunk Jul 12 '17 at 15:38
  • Looking at the performance Test linked above it seems to be pretty good to go with a bitwise operation: -parseInt seems to have the worst performance across all engines -Math.floor has very high performance - jumps between the different browsers (fast on chrome and firefox, slow on edge) – FrankKrumnow Apr 25 '18 at 11:21
  • A bit late in the game, but with JSPerf looking like dead in Summer 2022, I tried `>> 0`, `| 0`, `~~` and `Math.floor` on jsbench.me, perf.link and jsben.ch. All gave different rankings, but `>>` wins 2 out of 3, finishing second on perf.link, behind `Math.floor` (very suspicious). I'll go with the righ shift. – Ricardo Aug 12 '22 at 13:09
101

Note: You cannot use Math.floor() as a replacement for truncate, because Math.floor(-3.1) = -4 and not -3 !!

A correct replacement for truncate would be:

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

    return Math.floor(value);
}
Jackson
  • 9,188
  • 6
  • 52
  • 77
  • 1
    That depends on the desired behavior for negative numbers. Some uses need negative numbers to map to the more negative value (-3.5 -> -4) and some require them to map to the smaller integer (-3.5 -> -3). The former is normally called "floor". The word "truncate" is often used to describe either behavior. In my case, I was only going to feed it negative numbers. But this comment is a useful warning for those who DO care about negative number behavior. – mcherm Oct 16 '09 at 14:35
  • 29
    @mcherm: Then they do not seem to understand the term "truncate" correctly. Truncate does exactly as its name implies: it truncates digits. It is never (in the general sense) equivalent to floor or ceil. http://en.wikipedia.org/wiki/Truncation – Thanatos Apr 16 '12 at 07:18
  • 6
    `Math.trunc(value)` was added in ECMAScript 6 – 4esn0k Jul 31 '14 at 05:49
  • 4
    `floor` rounds towards -infinity, `truncate` rounds towards zero. (`ceil` rounds towards +infinity). – Peter Cordes Apr 24 '17 at 00:03
50

A double bitwise not operator can be used to truncate floats. The other operations you mentioned are available through Math.floor, Math.ceil, and Math.round.

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

More details courtesy of James Padolsey.

brad
  • 73,826
  • 21
  • 73
  • 85
  • 1
    This is probably a bad thing to do for production code (since it's obscure) but it was exactly what I needed for code-golfing [my `` font rendering engine in JS](http://canonical.org/~kragen/sw/dofonts.html). Thank you! – Kragen Javier Sitaker Feb 06 '12 at 20:31
  • 11
    This can also be accomplished with n | 0. – Jay Douglass Mar 20 '12 at 23:48
  • 19
    Note that either method (~~n or n|0) only work on numbers up to 2^31-1, or 2147483647. 2147483648 or higher will return an incorrect result; for example, 2147483647|0 returns -2147483648, and 4294967295|0 returns -1, which is almost definitely not what you want. – Ed Bayiates Oct 22 '12 at 18:36
43

For truncate:

var intvalue = Math.floor(value);

For round:

var intvalue = Math.round(value);
JP Silvashy
  • 46,977
  • 48
  • 149
  • 227
Mike
  • 8,853
  • 3
  • 35
  • 44
  • 7
    Math.floor does not truncate negative values. See answer above. Otherwise nice answer. – oligofren May 04 '12 at 14:47
  • If you're interested in performance I've put a small test case here: http://jsperf.com/dsafdgdfsaf/2 (var | 0 wins here). – Cybolic Jun 15 '12 at 23:54
41

You can use the parseInt method for no rounding. Be careful with user input due to the 0x (hex) and 0 (octal) prefix options.

var intValue = parseInt(floatValue, 10);

EDIT: as a warning (from the comments section), please be aware that certain numeric values will be converted to their exponent form such as 1e21 which results in the incorrect decimal representation of "1"

Graeme Wicksted
  • 1,770
  • 1
  • 18
  • 21
  • 1
    This is actually helpful when you just want the integer part of a decimal, without rounding up or down, which is what .round, .ceil, and .floor all do. – Judah Gabriel Himango Jan 30 '12 at 20:08
  • 2
    ...even when simply truncating this seems to be the slowest method. http://jsperf.com/float-to-int-conversion-comparison – Robert Koritnik Oct 11 '12 at 10:34
  • 2
    Always pass the 2nd value to parseInt to specify what base you're expecting. So, parseInt(floatValue, 10) to always get base 10. – Tim Tisdall Feb 22 '13 at 16:52
  • 4
    Though this is old, this question seems to be one that's quite often asked, so I'll put this here as a warning. If the value would be represented using "e" notation because of its size, it will just result in one digit, not what is expected. For example, `parseInt(1000000000000000000000, 10);` results in 1, not 1 000 000 000 000 000 000 000. Anyway, the question explicitly did not want "_converting to a string and parsing_", though that's relatively minor... ;) – Qantas 94 Heavy Nov 28 '13 at 02:04
  • 6
    @Qantas94Heavy The reason for this behaviour, is because [`parseInt()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt) expects a *string* not a number as its first parameter. When you pass this integer, it is converted to `1e21` and then `parseInt` parses the string `1e21`, which results in `1`. – Olaf Dietsche Jan 09 '14 at 20:56
  • 1
    ^ adding another example to the above comment, `parseInt(0.0000005)` results into `5` instead of `0` since it first gets converted into `5e-7`. So it's important to be a bit careful in case you are parsing integers instead of strings. – Rohan Chougule Apr 27 '21 at 14:21
  • `parseInt` is easy, but it's slow. According to the answer given by Kamil Kiełczewski in this thread it performs worse of all tested methods. It's better to just use `Math.round` or `Math.trunc`. `Math.trunc` returns only the integer part of the number. – Emanuel Lindström Jan 12 '22 at 15:42
19

Bit shift by 0 which is equivalent to division by 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Prasanth
  • 5,230
  • 2
  • 29
  • 61
  • 4
    Small note: `>> 0` seems to only work for integers < _2^31-1_, and `>>> 0` for integers < _2^32-1_. This returns 0 for larger values – Romuald Brunet Apr 23 '14 at 10:02
  • @RomualdBrunet, yes, JavaScript clearly defines all the bitwise operations as operating on 32 bit numbers. That's in the specs. – Alexis Wilke May 24 '14 at 02:51
  • This works as Javascript does bitwise operations only with 32bit (signed) integers as stated in an answer above. So any bit-operation that seems to do nothing (like a shift for 0, OR with 0, AND with 1, double NOT) still needs Javascript interpreter to convert the value to 32bit int. – FrankKrumnow Apr 25 '18 at 11:14
14

In your case, when you want a string in the end (in order to insert commas), you can also just use the Number.toFixed() function, however, this will perform rounding.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Russell Leggett
  • 8,795
  • 3
  • 31
  • 45
  • Just a reminder return value of toFixed is a string. eg. `$num1 = 12.2222.toFixed(2)` `$num2 = Number.parseFloat(12.2222).toFixed(2)`, $num1 and $num2 are "12.22" in string. – tinystone Feb 27 '23 at 07:05
13

One more possible way — use XOR operation:

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

Priority of bitwise operations is less then priority of math operations, it's useful. Try on https://jsfiddle.net/au51uj3r/

Ran Marciano
  • 1,431
  • 5
  • 13
  • 30
  • Nice, but be careful with this though. If you have `const num = -165.01295398373 * 10_000_000_000_000` then `Math.trunc(num)` will give you a correct `-1 650 129 539 837 300`, but `num ^ 0` gives `1 190 253 196`. (Note, Number.MIN_SAFE_INTEGER = -9 007 199 254 740 991) – 8bitjoey Mar 19 '23 at 10:54
13

If you want a rounded off answer on the downward side:

var intvalue = Math.floor( floatvalue );
var integer = Math.floor(4.56);
Answer = 4

If you want to round off upwards:

var intvalue = Math.ceil( floatvalue );
Answer would be = 5
Tim Muia
  • 183
  • 1
  • 7
10

To truncate:

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

To round:

console.log(Math.round( 1.5 ));  // 2
console.log(Math.round( 1.49 )); // 1
console.log(Math.round( -1.6 )); // -2
console.log(Math.round( -1.3 )); // -1
Ran Marciano
  • 1,431
  • 5
  • 13
  • 30
Razor
  • 27,418
  • 8
  • 53
  • 76
7

There are many suggestions here. The bitwise OR seems to be the simplest by far. Here is another short solution which works with negative numbers as well using the modulo operator. It is probably easier to understand than the bitwise OR:

intval = floatval - floatval%1;

This method also works with high value numbers where neither '|0' nor '~~' nor '>>0' work correctly:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295
Juliane Holzt
  • 2,135
  • 15
  • 14
  • If you refer to another answer, please either add a reference to it or shortly sketch its idea. – bertl Jul 11 '13 at 14:06
7
  1. Math.floor() function returns the largest integer less than or equal to a given number.

        console.log('Math.floor : ', Math.floor(3.5));
        console.log('Math.floor : ', Math.floor(-3.5));
  2. Math.ceil() function always rounds a number up to the next largest integer.

        console.log('Math.ceil : ', Math.ceil(3.5));
        console.log('Math.ceil : ', Math.ceil(-3.5));
  3. Math.round() function returns the value of a number rounded to the nearest integer.

        console.log('Math.round : ', Math.round(3.5));
        console.log('Math.round : ', Math.round(-3.5));
  4. Math.trunc() function returns the integer part of a number by removing any fractional digits.

        console.log('Math.trunc : ', Math.trunc(3.5));
        console.log('Math.trunc : ', Math.trunc(-3.5));
Sahil Thummar
  • 1,926
  • 16
  • 16
6

//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
  • 2,608
  • 1
  • 29
  • 33
4

Performance

Today 2020.11.28 I perform tests on MacOs HighSierra 10.13.6 on Chrome v85, Safari v13.1.2 and Firefox v80 for chosen solutions.

Results

  • for all browsers all solutions (except B and K) gives very similar speed results
  • solutions B and K are slow

enter image description here

Details

I perform test case which you can run HERE

Below snippet presents differences between solutions A B C D E F G H I J K L

function A(float) {
    return Math.trunc( float );
}

function B(float) {
    return parseInt(float);
}

function C(float) {
    return float | 0;
}

function D(float) {
    return ~~float;
}

function E(float) {
    return float >> 0;
}

function F(float) {
    return float - float%1;
}

function G(float) {
    return float ^ 0;
}

function H(float) {
    return Math.floor( float );
}

function I(float) {
    return Math.ceil( float );
}

function J(float) {
    return Math.round( float );
}

function K(float) {
    return float.toFixed(0);
}

function L(float) {
    return float >>> 0;
}






// ---------
// TEST
// ---------

[A,B,C,D,E,F,G,H,I,J,K,L]
  .forEach(f=> console.log(`${f.name} ${f(1.5)} ${f(-1.5)} ${f(2.499)} ${f(-2.499)}`))
This snippet only presents functions used in performance tests - it not perform tests itself!

And here are example results for chrome

enter image description here

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
3

If look into native Math object in JavaScript, you get the whole bunch of functions to work on numbers and values, etc...

Basically what you want to do is quite simple and native in JavaScript...

Imagine you have the number below:

const myValue = 56.4534931;

and now if you want to round it down to the nearest number, just simply do:

const rounded = Math.floor(myValue);

and you get:

56

If you want to round it up to the nearest number, just do:

const roundedUp = Math.ceil(myValue);

and you get:

57

Also Math.round just round it to higher or lower number depends on which one is closer to the flot number.

Also you can use of ~~ behind the float number, that will convert a float to a whole number.

You can use it like ~~myValue...

Alireza
  • 100,211
  • 27
  • 269
  • 172
  • Plase be careful with the `~~` because if the number is larger than the int 32 limit, it will change the value to the int 32 limit value. – Machado Oct 16 '19 at 14:15
1

I just want to point out that monetarily you want to round, and not trunc. Being off by a penny is much less likely, since 4.999452 * 100 rounded will give you 5, a more representative answer.

And on top of that, don't forget about banker's rounding, which is a way to counter the slightly positive bias that straight rounding gives -- your financial application may require it.

Gaussian/banker's rounding in JavaScript

Community
  • 1
  • 1
Gerard ONeill
  • 3,914
  • 39
  • 25
0

If you are using angularjs then simple solution as follows In HTML Template Binding

{{val | number:0}}

it will convert val into integer

go through with this link docs.angularjs.org/api/ng/filter/number

Jameel Grand
  • 2,294
  • 16
  • 32