по модулю — php fmod возвращает непригодный результат

fmod(floatval("314.6"), floatval("1.3"))
=> 1.1990408665952E-14

Я более или менее понимаю основную проблему представления чисел в двоичной форме и чего-то с помощью IEEE-754. Но: Как я могу получить результат, который можно использовать на практике?

Пример того, чего я хочу достичь: Продавец может определить цену P своего товара, но цена должна быть кратна x:

if (fmod(P, x) != 0) { echo "price must be a multiple of " . x; }

Это было бы так просто, но подход терпел неудачу всякий раз, когда я получаю что-то вроде 1234E-18 в качестве возвращаемого значения fmod(),
Что делать в реальной жизни, чтобы легко проверить ценовой интервал без использования пользовательского кода?

Этот или подобные вопросы были вокруг, но все, что я могу найти, это объяснения, почему fmod() ведет себя как это делает. Никогда не отвечайте, как решить эту реальную проблему …

2

Решение

Проблема здесь в том, что 314.6 это точно 1.3 * 242 так что остаток с плавающей точкой равен нулю, но вы получите 0.00000000000001199041 из-за неточностей IEEE 754, о которых вы хорошо знаете.

Но не забывайте одно из правил математики с плавающей точкой: вы не можете сравнить поплавки за равенство небрежно. Если ваши аргументы имеют одну десятичную позицию, вам не нужна точность в 14 позиций. У вас есть цены: сколько десятичных знаков имеет смысл в вашей валюте? Если вы использовали, например, евро, вы вряд ли будете использовать более двух (центов) и 1.1990408665952E-14 ноль для всех эффектов:

var_dump(round(1.1990408665952E-14, 2));

двойная (0)

Некоторые люди рекомендуют делать все математические расчеты с использованием целых чисел (например, центов вместо евро), чтобы избежать ошибок округления, но большинство реальных проблем возникают из-за очень специфических ошибок:

  • Отображение необработанных поплавков для пользователя (вместо округления и форматирования их).
  • Делать сырые сравнения (if ($foo == $bar)).

… И целые числа не предотвращают все ошибки округления в любом случае (например, расчеты налога по отдельным позициям, не совпадающие с расчетами по итоговым суммам счетов).

0

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

Других решений пока нет …

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