149

Is there any difference between these:

float foo1 = (int)(bar / 3.0);
float foo2 = floor(bar / 3.0);

As I understand both cases have the same result. Is there any difference in the compiled code?

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
OgreSwamp
  • 4,602
  • 4
  • 33
  • 54
  • 1
    a bit better with `floor`, but beware that this is for `double` not for `float`. C99 also has `floorf` for `float`. – Jens Gustedt Jul 21 '10 at 17:11
  • 3
    So they have same result as long as bar is positive – Zac Mar 06 '13 at 11:13
  • 1
    (note: in C++ please `#include` and use `std::floor`) – user202729 May 16 '18 at 03:25
  • What type is `bar`? – chux - Reinstate Monica Oct 29 '18 at 20:06
  • @chux Doesn't matter, divide by 3.0 will make it into double anyway – kaalus Apr 03 '20 at 13:44
  • @kaalus [3.0 will make it into double anyway](https://stackoverflow.com/questions/3300290/cast-to-int-vs-floor?noredirect=1#comment107942003_3300290) --> not quite. Depends on the type of `bar`. With most types, `bar/3.0` becomes `double`. Not so with `long double` or `complex`. [@Jens Gustedt](https://stackoverflow.com/questions/3300290/cast-to-int-vs-floor?noredirect=1#comment3420470_3300290) comment is good. With `bar` as `float`, `float foo2 = floorf(bar / 3.0f);` can make for more efficient code. – chux - Reinstate Monica Apr 03 '20 at 13:54

6 Answers6

241

Casting to an int will truncate toward zero. floor() will truncate toward negative infinite. This will give you different values if bar were negative.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 17
    I think you hit the nail on the head here. Another difference, if `floor()` is the intent, is if the value of `bar` is too big to fit in an `int`. – Fred Larson Jul 21 '10 at 14:44
  • Do you have any source for that statement? – HelloGoodbye May 22 '17 at 14:48
  • 2
    Even when the result is positive it's not guaranteed. See [this](https://stackoverflow.com/q/40453050) and [this](https://stackoverflow.com/questions/7517588). – user202729 May 16 '18 at 03:38
39

As was said before, for positive numbers they are the same, but they differ for negative numbers. The rule is that int rounds towards 0, while floor rounds towards negative infinity.

floor(4.5) = (int)4.5 = 4
floor(-4.5) = -5 
(int)(-4.5) = -4

This being said, there is also a difference in execution time. On my system, I've timed that casting is at least 3 times faster than floor.

I have code that needs the floor operation of a limited range of values, including negative numbers. And it needs to be very efficient, so we use the following function for it:

int int_floor(double x) 
{ 
    return (int)(x+100000) - 100000; 
}

Of course this will fail for very large values of x (you will run into some overflow issues) and for negative values below -100000, etc. But I've clocked it to be at least 3 times faster than floor, which was really critical for our application. Take it with a grain of salt, test it on your system, etc. but it's worth considering IMHO.

brice rebsamen
  • 664
  • 6
  • 11
  • "I've clocked it to be at least 3 times faster than floor" --> OP is using `float`, not `double` - perhaps `double` was your application. If in C, be sure to use `floorf()` with `float`s. – chux - Reinstate Monica May 16 '18 at 20:10
  • @chux I think the only reason there is any difference is that the cast allows for a compile-time optimization. So that conversion may actually have been completely removed during execution. – ClydeTheGhost Oct 29 '18 at 15:51
9

The difference according to cppinsights.io

float foo1 = (int)(bar / 3.0);
float foo2 = floor(bar / 3.0);

// becomes
float foo1 = static_cast<float>(static_cast<int>((static_cast<double>(bar) / 3.0)));
float foo2 = static_cast<float>(floor(static_cast<double>(bar) / 3.0));

// so

bar = 1.0

// gives

foo1 == 0;
foo2 == 0;
AndersK
  • 35,813
  • 6
  • 60
  • 86
  • 1
    What do you mean by `fabs`? The question was about `floor`. The floor of `0.33333`... is `0`. – Aaron Franke Mar 30 '18 at 04:15
  • 4
    @AaronFranke the original question has been modified. seems a lot can happen in 8 years ;-) notice other answers have the same premise – AndersK Jul 05 '18 at 04:52
3

EDIT: Because the question may have been modified due to confusion between fabs() and floor().

Given the original question example lines:

1.  float foo = (int)(bar / 3.0);

2.  float foo = fabs(bar / 3.0);

The difference is that if bar is negative the result will be negative with the first but positive with the second. The first will be truncated to an integer and the second will return the full decimal value including fractional part.

Amardeep AC9MF
  • 18,464
  • 5
  • 40
  • 50
2

There are two main differences:

  1. As others have pointed out, casting to an integer will truncate towards zero, whereas floor() will always truncate towards negative infinity; this is different behaviour for a negative operand.

  2. No one (yet) seems to have pointed out another difference - if your argument is greater than or equal to MAX_INT+1 (or less than -MAX_INT-1) then casting to an int will result in the top-most bits being dropped (C, probably) or undefined behaviour (C++ and possibly C). EG if your int is 32 bits, you will only have a sign bit plus 31 bits of data. So using this with a double that is large in size is going to produce unintended results.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • 2.a. The exact condition for the conversion to `int` overflowing is that the argument is greater or equal to `INT_MAX`+1. Symmetrically, the condition for the underflow is that the argument is lower or equal to `INT_MIN`-1. – Pascal Cuoq Dec 30 '14 at 22:22
  • 1
    2.b. Overflow in the conversion from floating-point to integer is undefined behavior in C++. It does not “result in the top-most bits being dropped”. See (although it is written for C): http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer – Pascal Cuoq Dec 30 '14 at 22:23
0

(int) x is a request to keep the integer part of x (there is no rounding here)

fabs(x) = |x| so that it's >= 0;

Ex: (int) -3.5 returns -3; fabs(-3.5) returns 3.5;

In general, fabs (x) >= x for all x;

x >= (int) x if x >= 0

x < (int) x if x < 0

Winter
  • 3,894
  • 7
  • 24
  • 56
Paul Hoang
  • 1,014
  • 2
  • 11
  • 21