2014-01-04 3 views
6

При использовании double fmod(double x, double y) и y - целое число, результат оказывается всегда точный.Является ли fmod() точным, когда y является целым числом?

(Это y целое точное число, но это не значит int здесь.)

Может быть, C не требуетfmod(), чтобы обеспечить точные ответы в этих отдельных случаях, но на компиляторы я попытался, то результат является точным, даже если частное значение x/y не является точно представимым.

  1. Являются ли точные ответы ожидаемыми, когда y является целым числом?
  2. Если нет, укажите пример счетчика.

Примеры:

double x = 1e10; 
// x = 10000000000 
printf("%.50g\n", fmod(x, 100)); 
// prints 0 

x = 1e60; 
// x = 999999999999999949387135297074018866963645011013410073083904 
printf("%.50g\n", fmod(x, 100)); 
// prints 4 

x = DBL_MAX; 
// x = 179769313486231570...6184124858368 
printf("%.50g\n", fmod(x, 100)); 
// prints 68 

x = 123400000000.0/9999; 
// x = 12341234.1234123408794403076171875 
printf("%.50g %a\n", fmod(x, 100), fmod(x, 100)); 
// prints 34.1234123408794403076171875 0x1.10fcbf9cp+5 

Примечания:
Мои double появляется в IEEE 754 binary64 требованиям.
Ограничения printf() здесь не касаются, только fmod().


[Редактировать]

Примечание: Под «Ожидаются точные ответы», я спрашиваю, если fmod() результат и математический результат точно такой же.

+0

Что вы подразумеваете под "точной" здесь? Как в «соответствует математическому результату»? –

+0

Вы правы. Извинения, бит сонный –

+0

@OliCharlesworth Да, «соответствует математическому результату» – chux

ответ

6

Стандарт IEEE 754 определяет операцию останова x REM y как математическую операцию x - (round(x/y)*y). Результат является точным по определению, даже если промежуточные операции x/y, round(x/y) и т. Д. Имеют неточные представления.

Как указывалось aka.nice, приведенное выше определение соответствует библиотечной функции remainder в libm. fmod определяется по-другому, требуя, чтобы результат имел тот же знак, что и x. Однако, поскольку разница между fmod и remainder равна либо 0, либо y, я считаю, что это все еще объясняет, почему результат является точным.

+0

+1 для цитаты. Я искал быстрое интуитивное объяснение того, почему всегда существует точный результат для 'x - (round (x/y) * y)' в пределах исходной точности, но он становился слишком сложным, поэтому я оставил его вне ответа. –

+2

Я не думаю, что есть простое объяснение.Наивное вычисление 'x-round (x/y) * y' не идентично' fmod (x, y) 'для некоторых крайних случаев, которые я пробовал (' x = pow (2, 53) * 100' и ​​'y = 100', например). Реализации должны выполнять трюки, такие как итеративное вычитание, чтобы результат был математически точным. –

+0

Лучшее объяснение, которое я знаю, начинается с вычитания 'r^n * y', где' r' является основанием, а 'n' - показателем, который дает результат, показатель которого совпадает с показателем' x'; это уменьшает количество точек точности, по крайней мере, до одного и дает значение, сравнимое с 'x' mod' y'. Я подозреваю, что вы применили этот аргумент индуктивно, чтобы получить заключение, но детали (особенно когда знаки переворачиваются) являются болью. –

10

Результат fmod is всегда точное; y - целое число не имеет значения. Конечно, если x и/или y уже являются приближениями некоторых действительных чисел a и b, то fmod(x,y) вряд ли будет в точности равным a mod b.

Смежные вопросы