Я получаю некоторые очень запутанные результаты при использовании функции 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
Я понятия не имею, что является причиной этого, и это создает некоторые уродливые ошибки в моей программе. Любое понимание будет с благодарностью. Заранее спасибо.
Поэтому, когда я вывожу первые результаты, как это:
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;
}
что я нашел из Вот даст вам правильный результат.
Здесь есть пара проблем.
Во-первых, ваш оператор печати усекает фактическое значение. По умолчанию для 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.