Что вообще здесь делает PHP? Ошибка правильно?

Почему на Земле $r2 имеет значение 2027?

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

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

(Я думаю, по какой-то причине (20,26 * 100) не приводит к точному целому числу, но ПОЧЕМУ??!? Разве это не ошибка?

2 ответа

Числа с плавающей точкой ведут себя неожиданным образом. (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().

Другие вопросы по тегам