1

My roommate just came up with a question.

Why in php (maybe other languages as well) floor($foo) and (int)$foo is 7?

$foo = (0.7 + 0.1) * 10;
var_dump(
    $foo,
    floor($foo),
    (int)$foo,
    ceil($foo),
    is_infinite($foo),
    is_finite($foo));

result

float(8)
float(7)
int(7)
float(8)
bool(false)
bool(true)

Notice that $foo is not an infinite number.

From answers I can see that everyone says that it is actually x.(9)

But what is reason behind number being x.(9) and not actual x as it should be in real life?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Minimihi
  • 408
  • 2
  • 11

4 Answers4

1

Not always. If you end up with 8.0000001 due to floating point imprecision, the floor will snap to 8. Sometimes it may be 7.999999, which will snap to 7.

Chances are, if you're multiplying 0.x by y(which is read as an int in most languages), it will come out whole, so you won't see this behavior.

This is similar in other languages as well.

Captain Skyhawk
  • 3,499
  • 2
  • 25
  • 39
1

Because 0.7 and/or 0.1 are internally actually 0.6999999.... or 0.09.....

That means your (0.7 * 0.1) comes out as something more like 0.7999..... After multiplying by 10 and int/flooring, you end up with 7.

Marc B
  • 356,200
  • 43
  • 426
  • 500
1

The floor function rounds down to nearest integer. Casting to int simply throws away the decimal part. $foo is a float, and it is not exactly 8, (must be 7.99999...) so you can observe that behavior.

jh314
  • 27,144
  • 16
  • 62
  • 82
1

A rational number will become a repeating decimal if the denominator contains a prime factor that isn't among the ones in the base's prime factor list (i.e. 2 and 5)

  • A rational number has an infinitely repeating sequence of finite length less than the value of the fully reduced fraction's denominator if the reduced fraction's denominator contains a prime factor that is not a factor of the base. The repeating sequence is preceded after the radix point by a transient of finite length if the reduced fraction also shares a prime factor with the base.

https://en.wikipedia.org/wiki/Repeating_decimal

Floating-point types in computers are almost always in binary, so any number whose denominator in the rational representation is not a power of 2 would be an infinite periodic decimal. For example 0.1 would be rounded to 0.100000001490116119384765625 in IEEE-754 single precision which is the nearest sum of power of 2s

Here none of 0.7 and 0.1 are representable in binary floating-point, and neither is 0.8. Their sum is also not equal to 0.8: try printing 0.7 + 0.1 == 0.8 and you'll get the result as false. It's actually slightly less than 0.8. But it's not a repeating decimal like 7.(9) as you though but a value with a finite number of 9s in the fractional part.

As a result the ceil and int result in 7. If you take the floor or round result you'll get 8

Community
  • 1
  • 1
phuclv
  • 37,963
  • 15
  • 156
  • 475