Несоответствия при использовании cmath’s fmod (C ++)

Я получаю некоторые очень запутанные результаты при использовании функции fmod.

Следующий код:

double x = pow(142, 35);
double y = fmod(x, 221);
std::cout << x << std::endl << y;

выходы:

2.13842e+75
206

Но когда трудно кодировать значение х:

double x = pow(142, 35);
double y = fmod(2.13842e+75, 221);
std::cout << x << std::endl << y;

Выход изменяется на:

2.13842e+75
14

Я понятия не имею, что является причиной этого, и это создает некоторые уродливые ошибки в моей программе. Любое понимание будет с благодарностью. Заранее спасибо.

4

Решение

Поэтому, когда я вывожу первые результаты, как это:

std::cout << std::fixed << x << std::endl << y << std::endl;

Я вижу это:

2138415301692701661114266637060519453227273059369895888628790658837784821760.000000
206.000000

когда я использовал этот номер выше для xс таким значением:

double y = fmod(2138415301692701661114266637060519453227273059369895888628790658837784821760.000000, 221);

тогда я получаю результат 206 за y из первого примера, основная проблема заключается в том, что вы достигаете предела с IEEE двухместный.

Обновить

Этот алгоритм для модульная мощность:

template <typename T>
T modpow(T base, T exp, T modulus) {
base %= modulus;
T result = 1;
while (exp > 0) {
if (exp & 1) result = (result * base) % modulus;
base = (base * base) % modulus;
exp >>= 1;
}
return result;
}

что я нашел из Вот даст вам правильный результат.

3

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

Здесь есть пара проблем.

Во-первых, ваш оператор печати усекает фактическое значение. По умолчанию для C ++
cout имеет точность 6. Он будет печатать только 6 десятичных знаков. Таким образом
следующие два отпечатка дают разные результаты, даже если они печатают одинаково
переменная:

double x = pow(142, 35);
std::cout << x << std::endl << y;
// prints 2.13842e+75
std::cout << std::fixed << x << std::endl << y << std::endl;
// prints 2138415301692701661114266637060519453227273059369895888628790658837784821760.0000000

Обратите внимание, что манипулятор std :: fixed используется для изменения вывода. Благодаря
@Shafik Yaghmour за предоставление манипулятора.

Во-вторых, даже значение, напечатанное выше, неверно из-за отсутствия точности
двойника. Двойник IEEE использует 52 бита для хранения мантиссы. Это
Достаточно для 15 до 17 цифр точности. Вам нужно использовать арбитраж
прецизионный калькулятор для определения фактического результата (например, bc
утилита командной строки).

% bc
142^35
2138415301692701650291828893190357329823022421032574372998179511073104723968
(142^35)%221
12

Глядя на эти два значения, первые 17 цифр соответствуют ожидаемым.

Увидеть http://en.wikipedia.org/wiki/Double-precision_floating-point_format за
дополнительная информация о лимитах IEEE double.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector