Почему на Земле $ r2 имеет значение 2027?
$r1 = ceil( 10.26 * 100); //equals 1026 - CORRECT.
$r2 = ceil( 20.26 * 100); //equals 2027 - WRONG!
(Я думаю, по какой-то причине (20,26 * 100) не приводит к точному целому числу, но ПОЧЕМУ ??!? Разве это не ошибка?
Числа с плавающей точкой ведут себя неожиданным образом. (Google статья «Каждый компьютерщик должен знать о плавающей точке» для деталей)
По сути, у компьютера нет возможности точно работать со значениями с плавающей запятой, поэтому вам всегда нужно ожидать каких-либо приближений в своих вычислениях (поэтому, кстати, вам НИКОГДА не следует представлять деньги как числа с плавающей запятой).
В вашем случае результат:
20,26 * 100
является
+2026,0000000000002
ceil
округляет до ближайшего целого числа, которое равно 2027, поэтому ответ правильный.
Нет, это не ошибка. Это связано с точностью чисел с плавающей точкой. Как вы, возможно, знаете, компьютер — это отдельная машина. Вещественные числа имеют бесконечно много чисел между двумя действительными числами: компьютер не может обрабатывать числа до бесконечности или даже, например, все числа от 0,00 до 0,01: между ними существует бесконечное число действительных чисел.
Ваш компьютер обрабатывает реал дискретно: все числа округляются до ближайшего представимого числа с плавающей запятой; поэтому числа с плавающей запятой всегда содержат ошибку представления (за исключением случаев, когда искомое число может быть представлено точно). Все мелкие ошибки в расчетах объясняют окончательную ошибку. Это то, что происходит в вашем случае. Для получения дополнительной информации и математического объяснения: https://en.wikipedia.org/wiki/Floating_point
Для примера в реальной жизни. Просто запустите этот фрагмент кода PHP и посмотрите, что произойдет:
$sum = 0.0;
for ($i = 0; $i < 1000; $i++) {
$sum += 0.1;
}
Вы ожидаете, что сумма станет ровно 100, верно?
Еще один совет о вашем фрагменте кода: если вы просто используете ceil () для получения целого числа, вам лучше использовать функцию round ().