Функция Haskell, вычисляющая e^x

Реализуйте функцию, которая вычисляет значение e ^ x, x — параметр функции, целое число. Для этого используйте разложение в ряд Тейлора, чтобы вычислить эффективность e. Функция получит в качестве параметра, помимо показателя степени x, количество членов ряда, которое будет работать как максимальное значение n. Для разрешения этой функции необходимо использовать рекурсию.

Я сделал это:

factorial 0 = 1
factorial n = n * factorial (n-1)

consigna3::Int->Int->Float
consigna3 _ 0 = 1
consigna3 x n = (fromIntegral(x^n) / fromIntegral(factorial n)) + consigna3 x (n-1)

Но некоторые результаты неверны, это то, что я ожидал:

Ejemplo 1: Main> funcion3 1 1
           2.0
Ejemplo 2: Main> funcion3 1 10
           2.718282
Ejemplo 3: Main> funcion3 2 10
           7.388997
Ejemplo 4: Main> funcion3 10 20
           21991.48
Ejemplo 5: Main> funcion3 10 30
           22026.46
Ejemplo 6: Main> funcion3 0 30
           1.0

Результаты (10 20) и (10 30) не соответствуют тому, что возвращает функция, которую я сделал. Что я делаю неправильно? Спасибо и извините за мой английский.


person Ignacio Mauricio Rios    schedule 09.10.2020    source источник
comment
Есть ли у вас ожидаемые результаты для funcion3, включающие 10 и меньшие значения для n? Я подозреваю, что funcion3 был реализован таким образом, что меньше подвержен влиянию ошибки округления с плавающей запятой.   -  person chepner    schedule 09.10.2020
comment
factorial 30 намного больше, чем максимальное значение Int. Вы должны использовать Integer для таких вычислений. Также я бы предложил Double вместо Float - вам нужна вся точность, которую вы можете получить, как вы это делаете.   -  person luqui    schedule 09.10.2020
comment
это действительно должно быть рассчитано в Rationals. используйте код в принятом ответе, но замените / на %. преобразовать только окончательный результат в число с плавающей запятой с помощью fromRational.   -  person Will Ness    schedule 16.07.2021


Ответы (1)


Вы используете Int для вычислений, которые переполнят Int. Вместо этого сразу конвертируйте в Float, а затем используйте Float для всего. Так:

consigna3 x n = ((fromIntegral x)^n / factorial (fromIntegral n)) + consigna3 x (n-1)

Здесь есть два важных изменения с Int на Float: во-первых, вы делаете x^n, где x :: Int, а я делаю fromIntegral x^n, где fromIntegral x :: Float; во-вторых, вы делаете factorial n, где n :: Int, а я делаю factorial (fromIntegral n), где fromIntegral n :: Float.

person Daniel Wagner    schedule 09.10.2020