16

Let's say I have x = 12.345. In javascript, what function floatToInt(x) has the fastest running time such that floatToInt(12.345) returns 12?

ambient
  • 2,896
  • 3
  • 16
  • 24
  • Are there multiple functions that do your job? – Bergi Dec 03 '15 at 22:29
  • 2
    Just use `Math.round` (or `Math.floor`, depending what you need). – Bergi Dec 03 '15 at 22:29
  • Is the speed of your conversion really worth making less readable code? – jfriend00 Dec 03 '15 at 22:32
  • @Bergi - is that the fastest way? Consider Hunterrex's insight below. How does the bitwise operator compare to Math.round or Math.floor? – ambient Dec 03 '15 at 22:32
  • 1
    And, you've done performance testing on your code and found that an integer conversion is the main bottleneck? I ask this because most of the time people spend time "speeding things" up, they are actually working on the wrong part of the problem and thus wasting their time and oftentimes complicating their code without much or any improvement. – jfriend00 Dec 03 '15 at 22:36
  • @cody: You were asking for a function, not an operation, and I'm not aware of anything else. Also, speed does not matter. – Bergi Dec 03 '15 at 22:41
  • also duplicate of [What is the best method to convert floating point to an integer in JavaScript?](http://stackoverflow.com/q/131406/1048572) – Bergi Dec 03 '15 at 22:45
  • @cody: `~~` has [important edge cases](http://stackoverflow.com/a/4055675/1048572) you would need to consider. And [it might not be faster at all](http://stackoverflow.com/a/5971774/1048572). – Bergi Dec 03 '15 at 22:46
  • 1
    @Bergi - you're in the forest and can't see the trees. I asked a simple question and was just looking for a simple answer, it is no more complicated than that. Thanks for the contribution, though! – ambient Dec 03 '15 at 22:54
  • Does this answer your question? [How can I round down a number in Javascript?](https://stackoverflow.com/questions/1435975/how-can-i-round-down-a-number-in-javascript) – Henke Jun 29 '21 at 18:06

5 Answers5

33

Great Question! I actually had to deal with this the other day! It may seem like a goto to just write parseInt but wait! we can be fancier.

So we can use bit operators for quite a few things and this seems like a great situation! Let's say I have the number from your question, 12.345, I can use the bit operator '~' which inverts all the bits in your number and in the process converts the number to an int! Gotta love JS.

So now we have the inverted bit representation of our number then if we '~' it again we get ........drum roll......... our number without the decimals! Unfortunately, it doesn't do rounding.

var a = 12.345;
var b = ~~a; //boom!

We can use Math.round() for that. But there you go! You can try it on JSperf to see the slight speed up you get! Hope that helps!

Hunterrex
  • 490
  • 5
  • 9
  • For example: `var a = 12.345' – Hunterrex Dec 03 '15 at 22:31
  • This is a great suggestion! Can you provide an example please? – ambient Dec 03 '15 at 22:31
  • 1
    An answer to a "fastest" question with NO documentation or supporting evidence showing your method is faster in multiple browsers is missing a lot. It may be faster, but you should show some evidence that it actually is faster in multiple browsers. – jfriend00 Dec 03 '15 at 22:34
  • That's not a very well designed performance test. It assumes that `Math.random()` always takes the exact same amount of time and that converting any possible result to an integer is always a constant time too. You should not have `Math.random()` in your test at all and you should be comparing a conversion of the same number for each method. Your method probably is faster, but this is a poorly designed test. When I run your test in Chrome, I see no meaingful difference between the first three methods. – jfriend00 Dec 03 '15 at 22:37
  • @Hunterrex that is some compelling evidence. – ambient Dec 03 '15 at 22:38
  • @cody - How is that compelling? The first three methods show basically the exact same performance. – jfriend00 Dec 03 '15 at 22:40
  • @jfriend00 I did not write these tests, but I agree. I would write better tests, but a little strained for time. – Hunterrex Dec 03 '15 at 22:45
  • 1
    @jfriend00: Agreed on "no meanigful difference", but `Math.random` is pretty much necessary for these kind of tests. It ensures that the operation is not constant-folded by an optimising compiler. Oh, microbenchmarks are hard… – Bergi Dec 03 '15 at 22:48
  • 2
    So, you write an answer to a question asking for the "fastest" method that shows no meaningful difference when using someone else's test and you have no time to make a test of your own? You haven't shown your answer is anything other than a "different" method of converting to an int. And, I'm even more surprised that the OP took the bait and seems to think this is a good way to code. – jfriend00 Dec 03 '15 at 22:56
  • @Bergi - `Math.random()` has to be outside the timed region so you can time only the operation that actually matters. – jfriend00 Dec 03 '15 at 22:58
  • 1
    @jfriend00: I don't think you can time a single `Math.round` call or `~~` operation with the tools that JS gives you. And if you're timing a loop (like jsperf does), `Math.random()` has to go in the body. But we can reasonably assume that every `Math.random()` call takes the same time (on average, at least), so that we can still compare the differences of the other operations. – Bergi Dec 03 '15 at 23:04
  • 1
    @Bergi - Why can't you do this: http://jsperf.com/float-to-int-conversion-comparison/27. This times 1000 calls of an array of random numbers where the array is pre-built outside the timed loop and the same randoms are used for each test case. – jfriend00 Dec 04 '15 at 01:35
  • 1
    @jfriend00: Notice that the test code runs multiple times (in a loop with dynamic length) after each initialisation ("setup code"), so you should not mutate `testNumbers`, it would only consist of integers after the first run. You'd need to move the `slice` inside the timed region. But the idea is good, if you don't trust `Math.random`, you should be able to do something [like that](http://jsperf.com/float-to-int-conversion-comparison/29) – Bergi Dec 04 '15 at 02:03
  • 3
    @Bergi - I see your point about the setup code. I changed it to just assign to a `resultArray` so the `testNumbers` array is never disturbed so no `.slice()` is needed and it always runs on the random numbers: https://jsperf.com/float-to-int-conversion-comparison/30. – jfriend00 Dec 04 '15 at 03:00
  • 3
    Be careful! With `x = 10000000000`: `Math.floor(x) === x`, but `~~x === 1410065408 `. `Math.floor(-0.5) === -1`, but `~~(-0.5) === 0` – Toxiro Mar 14 '20 at 00:55
  • use `b = ~~(a + 0.5)` for rounding – Chiu Jun 29 '20 at 05:29
8

this is a good example i think

var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue ); 
var intvalue = Math.round( floatvalue );
Firefog
  • 2,798
  • 7
  • 42
  • 75
5

just do: ~~(x + 0.5)

Cheers, Z.

zi88
  • 198
  • 4
  • 8
3

Arithmetic OR with zero does the trick.

> 12 === (0 | 12.245)
true
Ezward
  • 16,382
  • 6
  • 21
  • 30
0

If you don't care about the rounding specifics, Math.trunc() is easy, standard, and readable. I haven't tested performance, but it must be better than Math.round() and parseInt().

Jacktose
  • 628
  • 6
  • 17