Для больших значений X (около 700 и выше) вы достигнете предела диапазона для двойных чисел (10 ^ 308) и вызовете бесконечный цикл. Вы не можете ничего с этим поделать, вы должны либо ограничить диапазон ввода X, либо использовать некоторую библиотеку больших чисел, чтобы расширить диапазон.
Другой обходной путь - добавить это в ваш цикл:
if (sum > 1E305) {
// we'll most likely run into an infinite loop
break;
}
Обратите внимание, что после этого вы должны обрабатывать этот случай вне цикла, чтобы избежать печати очень большого неверного результата.
Я не могу воспроизвести проблему для 0.00000000001
, для меня это просто возвращает 1. Отрицательные значения тоже работают нормально, хотя результат неверен, что является ошибкой / ограничением в алгоритме. РЕДАКТИРОВАТЬ: Чтобы исправить это, мы можем использовать тот факт, что e^-x
совпадает с 1 / e^x
.
Код:
#include <stdio.h>
double CalcExp(double x){
double eps = 0.0000000000000000001;
double elem = 1.0;
double sum = 0.0;
bool negative = false;
int i = 1;
sum = 0.0;
if (x < 0) {
negative = true;
x = -x;
}
do {
sum += elem;
elem *= x / i;
i++;
if (sum > 1E305) break;
} while (elem >= eps);
if (sum > 1E305) {
// TODO: Handle large input case here
}
if (negative) {
return 1.0 / sum;
} else {
return sum;
}
}
int main() {
printf("%e\n", CalcExp(0.00000000001)); // Output: 1.000000e+000
printf("%e\n", CalcExp(-4)); // Output: 1.831564e-002
printf("%e\n", CalcExp(-45)); // Output: 2.862519e-020
printf("%e\n", CalcExp(1)); // Output: 2.718282e+000
printf("%e\n", CalcExp(750)); // Output: 1.375604e+305
printf("%e\n", CalcExp(7500000)); // Output: 1.058503e+305
printf("%e\n", CalcExp(-450000)); // Output: 9.241336e-308
return 0;
}