Вычисление e ^ x без использования каких-либо функций

StackOverflow https://stackoverflow.com/questions/827706

  •  06-07-2019
  •  | 
  •  

Вопрос

Предполагается, что мы вычисляем e ^ x, используя такую формулу:

e ^ x = 1 + (x ^ 1/1!) + (x ^ 2/2!) ......

Пока у меня есть этот код:

while (result >= 1.0E-20 )
{
    power = power * input;
    factorial = factorial * counter;
    result = power / factorial;
    eValue += result;
    counter++;
    iterations++;
}

Моя проблема сейчас в том, что, поскольку факториал имеет тип long long, я действительно не могу сохранить число больше 20!итак , что происходит , так это то , что программа выдает забавные цифры , когда достигает этой точки ..

Правильное решение может иметь значение X не более 709, поэтому e ^ 709 должно выводить:8.21840746155e+307

Программа написана на C++.

Это было полезно?

Решение

Как x^ n, так и n!быстро увеличивается с увеличением n (экспоненциально и сверхэкспоненциально соответственно) и вскоре переполнит любой тип данных, который вы используете.С другой стороны, x^n/n!идет вниз (в конце концов), и вы можете остановиться, когда он станет небольшим.То есть, используйте тот факт, что x^(n+1)/(n+1)!= (x^n/n!) * (x/(n+1)).Вот так, скажем:

term = 1.0;
for(n=1; term >= 1.0E-10; n++)
{
    eValue += term;
    term = term * x / n;
}

(Код, введенный непосредственно в это поле, но я ожидаю, что он должен сработать.)

Редактировать:Обратите внимание, что термин x^n/n!является, при большом x, увеличивающимся некоторое время, а затем уменьшающимся.Для x = 709 оно увеличивается до ~ 1e + 306, прежде чем уменьшиться до 0, что находится как раз в пределах того, что double может справиться (doubleдиапазон составляет ~ 1e308 и term*x отодвигает это на второй план), но long double работает нормально.Конечно, ваш окончательный Результат ex больше любого из терминов, поэтому, предполагая, что вы используете тип данных, достаточно большой, чтобы вместить результат, все будет в порядке.

(Для x =709 вам может сойти с рук использование просто double если вы используете term = term / n * x, но это не работает для 710.)

Другие советы

Что произойдет, если вы измените тип factorial От long long Для double?

Я могу придумать другое решение.Пусть pow(e,x) = pow(10, m) * b где b является >=1 и < 10, тогда

m = trunc( x * log10(e) )

где в log10(e) является постоянным фактором.

и

b = pow(e,x)/pow(10, m ) = pow(e,x)/pow(e,m/log10(e)) = pow (e,x-m/log10(e))

Этим вы получаете:

z = x-m/log10(e)

который будет находиться в диапазоне от 0 до 3, а затем использовать b = pow(e,z) как указано SreevartsR.

и окончательный ответ таков

b - основание (значащая цифра), а m - мантисса (порядок величины).

это будет быстрее, чем подход SreevartsR, и вам, возможно, не потребуется использовать высокую точность.

Желаю удачи.

Это будет работать даже тогда, когда x меньше 0 и больше отрицательного значения, в этом случае z будет находиться в диапазоне от 0 до -3, и это будет быстрее, чем любой другой подход.

Поскольку z равно от -3 до 3, и если вам требуются первые 20 значащих цифр, то выражение pow (e, z) может быть вычислено до 37 членов только начиная с 3 ^ 37/37!= ~ 3.2е-26.

То, что вы представили здесь, является приложением Схема Хорнера для вычисления многочленов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top