Функция MOD(0.9, 0.3) в Excel возвращает неожиданный результат

Вопрос или проблема

Функция MOD в Excel должна возвращать остаток от деления в Excel

Я считаю, что функция =MOD(0.9, 0.3) должна возвращать 0, так как, по сути, 0.3*3 это 0.9

Но она возвращает 5.55112E-17

Есть подсказки по поводу того, в чем дело?

Это не ошибка! Excel использует двойную точность IEEE-754, и, как и любые другие числа с плавающей запятой в двоичной системе, невозможно точно представить десятичные значения, такие как 0.9 или 0.3. Фактические значения просто очень близки к ним,
0.90000000000000002220446049250313080847263336181640625
и
0.299999999999999988897769753748434595763683319091796875 если быть точным.

Результат операции по модулю равен
5.5511151231257827021181583404541015625 × 10-17, что является очень маленьким значением, почти нулем, и Excel отображает его округленным до 5.55112E-17, так что здесь нет ничего неправильного! Почти все языки программирования используют двоичные числа с плавающей запятой и дадут тот же результат для аналогичных операций

Чтобы это исправить, вы можете:

Повторяющиеся двоичные числа и вычисления, которые дают результаты, близкие к нулю

Еще одна запутанная проблема, влияющая на хранение чисел с плавающей запятой в двоичном формате, заключается в том, что некоторые числа, которые являются конечными, не повторяющимися числами в десятичной системе, являются бесконечными, повторяющимися числами в двоичной системе. Наиболее распространенным примером этого является значение 0.1 и его вариации. Хотя эти числа могут быть идеально представлены в десятичной системе, то же самое число в двоичном формате становится следующим повторяющимся двоичным числом, когда оно хранится в мантиссе:

000110011001100110011 (и так далее)

Спецификация IEEE 754 не делает никаких особых допущений для какого-либо числа. Она хранит то, что может в мантиссе, и обрезает остальное. В результате возникает ошибка около -2.8E-17, или 0.000000000000000028, когда оно сохраняется.

Даже обычные десятичные дроби, такие как десятичное 0.0001, не могут быть точно представлены в двоичном формате. (0.0001 — это повторяющаяся двоичная дробь с периодом 104 бита). Это похоже на то, почему дробь 1/3 не может быть точно представлена в десятичной системе (повторяющийся 0.33333333333333333333).

Дальнейшее чтение

Excel использует Visual Basic для своего программирования. Таким образом, Microsoft ссылается на операцию mod как на

Неточность с плавающей запятой
Когда вы работаете с числами с плавающей запятой,
имейте в виду, что они не всегда имеют точное представление в
памяти. Это может привести к неожиданным результатам от некоторых операций,
таких как сравнение значений и оператор Mod.

В моем случае MOD(0.15,0.05) возвращает 0.05, когда должно быть ноль (0.05 входит ровно три раза в 0.15). Это выглядит как ошибка.

Так что я избегаю функции MOD() и вместо этого использую:

num1/num2 - trunc(num1/num2))*num2

округленное до 10 десятичных знаков.

Похоже, что это ошибка с плавающей запятой в Excel

http://www.excelforum.com/excel-formulas-and-functions/927962-mod-function-behaving-badly.html

Ответ или решение

Функция MOD в Excel, выполняющая операцию остатка от деления, может возвращать неожиданные результаты из-за особенностей представления чисел с плавающей запятой (floating-point) в памяти компьютера. Рассмотрим обращение функции =MOD(0.9, 0.3), которое возвращает 5.55112E-17, вместо ожидаемого значения 0.

Причина проблемы:

Excel использует стандарт IEEE-754 для представления чисел с плавающей запятой, что означает, что определенные десятичные числа не могут быть точно представлены в двоичной системе. В данном случае, числа 0.9 и 0.3 представляются как:

  • 0.90000000000000002220446049250313080847263336181640625 (фактическое значение 0.9)
  • 0.299999999999999988897769753748434595763683319091796875 (фактическое значение 0.3)

Когда вы выполняете операцию MOD с этими числами, результатом является незначительная разница, которая округляется и отображается Excel как 5.55112E-17. Это значение очень близко к нулю, но отличающееся от него, что и вызывает недоумение.

Как исправить проблему:

  1. Округление результата: Вы можете округлить результат вычисления, например, до одного знака после запятой. Используйте функцию ROUND, как показано ниже:

    =ROUND(MOD(0.9, 0.3), 1)
  2. Изменение числа отображаемых знаков: В настройках Excel вы можете изменить количество отображаемых знаков после запятой, тем самым скрыв незначительное значение.

  3. Использование VBA: Для более точных вычислений можно воспользоваться языком программирования VBA, который поддерживает тип данных Decimal с более высокой точностью. Вы можете создать пользовательскую функцию для работы с более точными числами.

Function ModuloDecimal(num1 As Decimal, num2 As Decimal) As Decimal
    ModuloDecimal = num1 - Int(num1 / num2) * num2
End Function
  1. Использование альтернативных методов: Вы можете воспользоваться альтернативными формулами для вычисления остатка, например:
    =num1 - INT(num1 / num2) * num2

Дополнительная информация:

Некоторые дробные значения, такие как 0.1 и 0.3, являются конечными и не повторяющимися в десятичной системе, но превращаются в бесконечные повторяющиеся двоичные числа в двоичной системе. Это приводит к потерям точности, аналогично тому, как дробь 1/3 не может быть точно представлена в десятичной системе (0.333…).

Для более подробной информации о проблемах с числами с плавающей запятой в Excel, вы можете ознакомиться с документацией Microsoft или другими источниками, упомянутыми в обсуждении выше.

Оцените материал
Добавить комментарий

Капча загружается...