Функция fmod возвращает неверный результат

Я получаю fmod, возвращая неправильный результат, я делаю что-то не так?

for($i = 0.00; $i < 1; $i = $i + 0.05) {
var_dump($i." = ".fmod($i, 0.05));
}

Выход:

0.= 0
0.05 = 0
0.1 = 0
0.15 = 1.3877787807814E-17
0.2 = 0
0.25 = 0.05
0.3 = 0.05
0.35 = 0.05
0.4 = 0.05
0.45 = 0.05
0.5 = 0.05
0.55 = 0.05
0.6 = 0.05
0.65 = 0.05
0.7 = 2.7755575615629E-17
0.75 = 6.9388939039072E-17
0.8 = 1.1102230246252E-16
0.85 = 1.5265566588596E-16
0.9 = 1.942890293094E-16
0.95 = 2.3592239273285E-16

Я ожидал, что каждый результат будет одинаковым: 0.

0

Решение

Первый, fmod это точно. Потому что это может: когда x а также y являются числами с плавающей точкой, математический результат fmod(x,y) может быть представлен точно как число с плавающей точкой.

Во-вторых, когда ты пишешь 0.05, вы не получите точно это число, потому что 5/100 с другой стороны не может быть представлено точно как число с плавающей запятой; и когда ты пишешь +вы не получите математическое сложение вообще, потому что результат этого математического сложения не всегда может быть представлен как число с плавающей запятой (*).

Начиная с 0,0 и многократного добавления 0,05, вы вскоре окажетесь неточными + территория, потому что в двоичном представлении лучшее представление 0,05 имеет много цифр. По мере увеличения суммы последние цифры постепенно должны быть отброшены. Это где неточность + исходит и, в конечном счете, является причиной, по которой fmod не дает вам ожидаемых результатов.

Это не имеет значения, что 0.05 не точно 5/100, если многократно добавлять его к нулю всегда было точно. Но так как число с плавающей точкой 0.05 имеет много цифр в двоичном (в отличие от десятичного), и так как некоторые из этих цифр должны быть потеряны при вычислении кратных 0.05, значение, которое вы получите для большинства магазинов y из 0.05 при расчете fmod(y, 0.05) не равно нулю, но представляет разницу между математическим умножением соответствующего целого числа на 0.05 и приближение y из этого числа.

(*) когда математическая сумма может быть представлена, математическая сумма — это то, что вы получаете, но иногда это просто невозможно.

1

Другие решения

Этот ответ относится к первой редакции вопроса:

https://stackoverflow.com/revisions/28372286/1

Все работает нормально! Вы можете рассчитать это для себя:

fmod(0.5, 0.25);
fmod(0.5, 0.23);
fmod(0.5, 0.20);

0.25 * 2 = 0.50   | Rest 0.00
0.23 * 2 = 0.46   | Rest 0.04
0.20 * 2 = 0.40   | Rest 0.10
0

По вопросам рекламы [email protected]