87

In C# the following code returns 2:

double d = 2.9;
int i = (int)d;
Debug.WriteLine(i);

In Javascript, however, the only way of converting a "double" to an "int" that I'm aware of is by using Math.round/floor/toFixed etc. Is there a way of converting to an int in Javascript without rounding? I'm aware of the performance implications of Number() so I'd rather avoid converting it to a string if at all possible.

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Rory Harvey
  • 2,579
  • 2
  • 22
  • 27
  • 7
    Why did you rule out `Math.floor`? – Quentin Dec 05 '11 at 16:30
  • 4
    The answers advising you to use "parseInt()" may all convert to a string internally first, because that's what "parseInt()" expects. Really, either "Math.floor()" or else "~~num" (double "not" operation) will truncate your double-precision value to an integer. – Pointy Dec 05 '11 at 16:53
  • He probably rules out ```Math.floor``` because it behaves different for negative numbers. Compare ```Math.floor(-2.5)``` and ```-2.5|0```. – Fox32 Jan 09 '17 at 12:04
  • Discarding the fractional part is ALWAYS rounding, per definition. You probably want: `rounding towards zero.` – Roland Oct 18 '18 at 10:59

9 Answers9

200

Use parseInt().

var num = 2.9
console.log(parseInt(num, 10)); // 2

You can also use |.

var num = 2.9
console.log(num | 0); // 2
Rooke
  • 2,013
  • 3
  • 22
  • 34
kubetz
  • 8,485
  • 1
  • 22
  • 27
  • 3
    May want to add a radix (10) as the second parameter – Adam Rackis Dec 05 '11 at 16:31
  • parseInt(num, 10); -- you added it to the console.log call, not parseInt – Adam Rackis Dec 05 '11 at 16:37
  • 2
    failure to add it would result in parseInt("09") returning 0 – Adam Rackis Dec 05 '11 at 16:38
  • @AdamRackis: Not my day, argh! Changed once again. Thank you for being my eyes :). – kubetz Dec 05 '11 at 16:41
  • 4
    The OR method seems to work perfectly, and doesn't rely on string conversion – Rory Harvey Dec 05 '11 at 17:18
  • TypeScript doesn't support passing a double value into `parseInt`, so I used the second option. Thanks! – NobleUplift Nov 01 '18 at 15:37
  • I would recommend strongly against using `parseInt` for converting a `double` to an `int`. `parseInt` expects a `string` argument and JS represents long `double` strings in scientific notation. Run `parseInt(0.0000005);` and see what the result is, you'll be shocked. – cbender Feb 22 '22 at 16:09
  • `let n = 0x1_0000_0000 + 2.9;` n is 4_294_967_298.9. As expected, `parseInt(n)` is 4_294_967_298. However, `n|0` is 2! That's because, for bitwise operations, JS keeps only the low 32 bits and zeros out the higher bits. Being much faster, OR'ing is nevertheless to be preferred. But do beware of its limitations! And also be aware `parseInt` fails for small numbers where the string representation is scientific Isee cbender, above). – George May 03 '23 at 22:27
64

I find the "parseInt" suggestions to be pretty curious, because "parseInt" operates on strings by design. That's why its name has the word "parse" in it.

A trick that avoids a function call entirely is

var truncated = ~~number;

The double application of the "~" unary operator will leave you with a truncated version of a double-precision value. However, the value is limited to 32 bit precision, as with all the other JavaScript operations that implicitly involve considering numbers to be integers (like array indexing and the bitwise operators).

edit — In an update quite a while later, another alternative to the ~~ trick is to bitwise-OR the value with zero:

var truncated = number|0;
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 3
    A nice trick, but not very readable, so not recommended for shared codebases. – Colin Basnett Nov 19 '18 at 23:14
  • 1
    @ColinBasnett it's idiomatic (both `~~` and `|0`) in JavaScript, and certainly better than `parseInt()` which really makes no sense. JavaScript doesn't really have integers except in transient form in the middle of expressions involving binary operators. – Pointy Nov 19 '18 at 23:34
37

Similar to C# casting to (int) with just using standard lib:

Math.trunc(1.6) // 1
Math.trunc(-1.6) // -1
Roland
  • 4,619
  • 7
  • 49
  • 81
  • 5
    I don't understand why it has so few upvotes, for somebody that doesn't do javascript everyday it seems to be the most straighforward and readable way to achieve this. I know if I try "| 0" or "~~" of other answers, I will never remember what it does and I'll be confused when I will see it next time. At least your solution is self explanatory. Thanks ! – AFract Feb 12 '20 at 14:30
  • @AFract agreed, few upvotes maybe because it was answered 7 years later :( – Loki Feb 22 '21 at 05:26
  • @Loki Few upvotes? This is my top answer, and it is has risen to 3rd place in the list of 7 answers. Not bad at all :-) – Roland Feb 22 '21 at 10:57
  • @brc-dd As I appreciate your effort to edit my answer, I feel that the sense of simplicity got lost. I am considering Rollback. In my view, Run Code Snippet is useful for complex code where it is not obvious it works just by inspecting the code. Here it seems useless overkill. Also, why mention ES6 if OP already mentioned Math.Floor etc? – Roland Feb 22 '21 at 16:42
  • 1
    @Roland `Math.floor` is available in JS since its very initial versions (ES1). `trunc` was added later, and if one wants compatibility with browsers like Internet Explorer, they surely cannot use `trunc` (unlike floor/round/~~/parseInt, they work on IE as well). Yeah, you can remove the snippet if you feel like simplicity is lost. :) – brc-dd Feb 22 '21 at 17:21
  • @brc-dd Your comment on ES6 would be a great comment that I would be glad to upvote – Roland Feb 22 '21 at 17:55
  • 1
    @Roland, relatively...I think this answer should be on 1st :) – Loki Mar 08 '21 at 09:21
  • @Loki just wait for 39 others to agree with you and to vote me up and this answer will rise one step :-) – Roland Mar 08 '21 at 10:16
9

Just use parseInt() and be sure to include the radix so you get predictable results:

parseInt(d, 10);
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
5

There is no such thing as an int in Javascript. All Numbers are actually doubles behind the scenes* so you can't rely on the type system to issue a rounding order for you as you can in C or C#.

You don't need to worry about precision issues (since doubles correctly represent any integer up to 2^53) but you really are stuck with using Math.floor (or other equivalent tricks) if you want to round to the nearest integer.


*Most JS engines use native ints when they can but all in all JS numbers must still have double semantics.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • 3
    All JS engines use native ints when they can (note that ranges differ: V8 notably special cases 31-bit ints). Even SpiderMonkey almost two decades ago used native ints when they can (when it was written, it was common for desktop computers to not have hardware floating-point support, so it was a very necessary performance optimization). – gsnedders Dec 05 '11 at 17:08
2

A trick to truncate that avoids a function call entirely is

var number = 2.9
var truncated = number - number % 1;
console.log(truncated); // 2 

To round a floating-point number to the nearest integer, use the addition/subtraction trick. This works for numbers with absolute value < 2 ^ 51.

var number = 2.9
var rounded = number + 6755399441055744.0 - 6755399441055744.0;  // (2^52 + 2^51)
console.log(rounded); // 3 

Note:

Halfway values are rounded to the nearest even using "round half to even" as the tie-breaking rule. Thus, for example, +23.5 becomes +24, as does +24.5. This variant of the round-to-nearest mode is also called bankers' rounding.

The magic number 6755399441055744.0 is explained in the stackoverflow post "A fast method to round a double to a 32-bit int explained".

// Round to whole integers using arithmetic operators
let trunc = (v) => v - v % 1;
let ceil  = (v) => trunc(v % 1 > 0 ? v + 1 : v);
let floor = (v) => trunc(v % 1 < 0 ? v - 1 : v);
let round = (v) => trunc(v < 0 ? v - 0.5 : v + 0.5);

let roundHalfEven = (v) => v + 6755399441055744.0 - 6755399441055744.0; // (2^52 + 2^51)

console.log("number  floor   ceil  round  trunc");
var array = [1.5, 1.4, 1.0, -1.0, -1.4, -1.5];
array.forEach(x => {
    let f = x => (x).toString().padStart(6," ");
    console.log(`${f(x)} ${f(floor(x))} ${f(ceil(x))} ${f(round(x))} ${f(trunc(x))}`);  
});
Amr Ali
  • 3,020
  • 1
  • 16
  • 11
1

As @Quentin and @Pointy pointed out in their comments, it's not a good idea to use parseInt() because it is designed to convert a string to an integer. When you pass a decimal number to it, it first converts the number to a string, then casts it to an integer. I suggest you use Math.trunc(), Math.floor(), ~~num, ~~v , num | 0, num << 0, or num >> 0 depending on your needs. This performance test demonstrates the difference in parseInt() and Math.floor() performance. Also, this post explains the difference between the proposed methods.

1man
  • 5,216
  • 7
  • 42
  • 56
1

I think that the easiest solution is using the bitwise not operator twice:

const myDouble = -66.7;
console.log(myDouble); //-66.7
const myInt = ~~myDouble;
console.log(myInt); //-66
const myInt = ~~-myDouble;
console.log(myInt); //66
Duloren
  • 2,395
  • 1
  • 25
  • 36
0

What about this:

if (stringToSearch.IndexOfAny( ".,;:?!".ToCharArray() ) == -1) { ... }
4b0
  • 21,981
  • 30
  • 95
  • 142
Beluga
  • 1
  • 3
    Please add more of an explanation. How does the very very small peice of code help the OP with their problem? There are 7 other well-recieved solutions to this question, if none of those solutions help you, you may ask another question. – Tyler2P Jul 15 '21 at 20:21