Math.IEEERemainder возвращает отрицательные результаты. Почему?

Инфраструктура .net включает Math.IEEERemainder (x, y) в дополнение к стандартному оператору модификации. Что на самом деле делает эта функция? Я не понимаю отрицательных чисел, которые это дает.

Пример:

Math.IEEERemainder(0, 2) = 0
Math.IEEERemainder(1, 2) = 1
Math.IEEERemainder(2, 2) = 0
Math.IEEERemainder(3, 2) = -1

person Jeffrey    schedule 01.10.2008    source источник


Ответы (1)


Если вы читали пример, приведенный на странице MSDN System.Math.IEEERemainder, вы заметите, что два положительных числа могут иметь отрицательный остаток.

Возвращаемое значение

Число, равное x - (y Q), где Q - частное от x / y, округленное до ближайшего целого числа (если x / y находится на полпути между двумя целыми числами, возвращается четное целое число).

Итак: 3 - (2 * (round (3/2))) = -1

/*
...
Divide two double-precision floating-point values:
1) The IEEE remainder of 1.797693e+308/2.00 is 0.000000e+000
2) The IEEE remainder of 1.797693e+308/3.00 is -1.000000e+000
Note that two positive numbers can yield a negative remainder.

*/

Эпилог

Фактический вопрос может заключаться в том, почему у нас есть две операции с остатком? Имея дело с данными с плавающей запятой, вы всегда должны быть осведомлены о своем стандарте с плавающей запятой. Поскольку мы живем в 21 веке, почти все работает на IEEE 754, и очень немногие из нас беспокоятся, скажем, о VAX F_Float по сравнению с IEEE 754.

В стандарте C # говорится, что оператор остатка (раздел 7.7. 3) в применении к аргументам с плавающей запятой аналогичен оператору остатка в применении к целочисленным аргументам. То есть одна и та же математическая формула 1 используется (с дополнительными соображениями для угловых случаев, связанных с представлениями с плавающей запятой) как в операциях с целыми числами, так и в операциях с остатками с плавающей запятой.

Поэтому, если вы хотите, чтобы ваши операции с остатком для чисел с плавающей запятой соответствовали вашим текущим режимам округления IEEE 754, рекомендуется использовать Math.IEEERemainder. Однако, если ваше использование не особенно чувствительно к тонкой разнице в округлении, производимой оператором остатка C #, продолжайте использовать оператор.

  1. Дано: z = x% y, тогда z = x - (x / y) * y
person user7116    schedule 01.10.2008
comment
Это именно то, что я как раз собирался опубликовать. Уберись из моей головы. ;) - person Jeff Yates; 01.10.2008
comment
@ffpf: ха-ха, вот интересный пост о том, зачем вам Modulo и IEEERemainder. Можете обыграть меня, добавив это, если хотите: D - person user7116; 01.10.2008
comment
@sixlettervariables: Нет, я не спрашиваю. Боюсь ответа. - person Jeff Yates; 01.10.2008
comment
@ffpf: наслаждайтесь ответом, это не потрясающе. - person user7116; 01.10.2008
comment
Режимы округления IEEE 754 не влияют ни на операцию IEEERemainder, ни на операцию %, потому что оба они точны. Точность означает, что результат будет одинаковым независимо от режима округления. Что между ними различается, так это лежащее в основе понятие интегрального частного. IEEERemainder округляет математическое частное до ближайшего целого числа, чтобы получить q в x - q * y. - person Pascal Cuoq; 13.01.2016
comment
Вы говорите, что почти все находится на IEEE 754, но я не понимаю, насколько это актуально, поскольку вопрос в том, почему C # (и большинство других языков) явно НЕ реализуют IEEE 754 для оператора модуля. - person BlueRaja - Danny Pflughoeft; 07.06.2017