-5

Why on Earth does $r2 have the value 2027?

$r1 = ceil( 10.26 * 100);  //equals 1026 - CORRECT.

$r2 = ceil( 20.26 * 100);   //equals 2027 - WRONG!

(I guess for some reason (20.26 * 100) does not result in an exact integer, but WHY??!? Isn't this a bug?

Tom Carnell
  • 585
  • 8
  • 14
  • 5
    See [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – RiggsFolly Aug 26 '15 at 12:28
  • You're multiplying by a floating point number. Why would it result in an integer? – Bill the Lizard Aug 26 '15 at 12:29
  • One would expect an integer because he's calling ceil which return an integer. – a2800276 Aug 26 '15 at 12:33
  • 1
    Ceil never said it would return Integer. Read Docs. – anwerj Aug 26 '15 at 12:37
  • 3
    possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – gmo Aug 26 '15 at 12:56
  • @anwerjunaid not sure what docs you are referring to, the php.net reference says: "Returns the next highest integer value by rounding up value if necessary." --http://php.net/manual/en/function.ceil.php – a2800276 Aug 26 '15 at 19:44
  • Dude integer value does not mean type integer. – anwerj Aug 27 '15 at 03:09
  • @a2800276 "I guess for some reason (20.26 * 100) does not result in an exact integer..." That does not include the call to `ceil`. – Bill the Lizard Aug 28 '15 at 21:07
  • "Dude", nobody said anything about integer types. In fact $r2 == 2027 even though it's of type `double`. You said ceil "never said" it returns an integer, when that's literally what it says in the reference documentation. – a2800276 Aug 29 '15 at 13:15

2 Answers2

1

Floating point numbers behave in unexpected ways. (Google the article "Every Computer Scientist Should Know About Floating-Point" for details)

Basically, the computer has no way to precisely work with floating point values, so you always need to expect some approximations in your calculations (which incidentally is why you should NEVER EVER represent money as floating point).

In your case, the result of:

20.26 * 100

is

2026.0000000000002

ceil rounds up to the nearest integer, which is 2027, so the answer is correct.

a2800276
  • 3,272
  • 22
  • 33
0

No this isn't a bug. This has to do with the precision of floating point numbers. As you might know, a computer is a discrete machine. Real numbers have infinitely many numbers between two reals: It is impossible for a computer to handle numbers to infinity, or even all numbers between 0.00 and 0.01 for example: There are an infinite number of reals in between.

Your computer handles reals discretely: All numbers get rounded to the closest representable floating point number; therefore floating point numbers always contain a representation error (except when the real you're looking for can be represented exactly). All small errors in the calculations account for the final error. This is what happens in your case. For more information, and the mathematical explanation: https://en.wikipedia.org/wiki/Floating_point

For an example in real life. Just run this piece of PHP code and see what happens:

$sum = 0.0;
for ($i = 0; $i < 1000; $i++) {
    $sum += 0.1;
}

You would expect sum to become exactly 100, right?

Another tip about your piece of code: If you're just using ceil() to get an integer, you'd better use the round() function.

Keugels
  • 790
  • 5
  • 15