Нет значения в функции числового интегрирования Python

Я пытаюсь написать код, который вычисляет интегралы с использованием прямоугольного правила, а также позволяет пользователю вводить интегральные пределы и количество делений (прямоугольников). Я написал функцию, но для определенных значений она просто возвращает «Нет». Есть идеи, почему?

Вот мой код:

def integral(f, a, b, N):
h = int((b-a)/N)
result = 0
result += h * f(a)
for i in range(1, N-1):
    result += h * f(a + i*h)
    return result

def f(x):          
return x**3

string_input1 = input("Please enter value for a: ") 
a = int(string_input1)


string_input2 = input("Please enter value for b: ")
b = int(string_input2)

while True: 
string_input3 = input("Please enter integer positive value for N: ") 
N = int(string_input3)
if N>0:       
    break


print(integral(f, a, b, N))

пример значений, которые возвращают "Нет", это a=0 b=1 N=2


person Eve    schedule 21.03.2017    source источник
comment
@WillemVanOnsem Вы уверены насчет отступа return result? это могло бы объяснить None, если N=2.   -  person DeepSpace    schedule 21.03.2017
comment
@DeepSpace: ну, программа изначально была задумана плохо. У меня была идея, что я исправил это, но я не могу знать наверняка. Судя по старому отступу, он был в цикле, но кто может знать наверняка?   -  person Willem Van Onsem    schedule 21.03.2017
comment
Теперь я понимаю, что h int был глупым, изменил его на число с плавающей запятой, но все равно получил None   -  person Eve    schedule 21.03.2017
comment
@Eve: оператор return внутри или снаружи цикла for?   -  person Willem Van Onsem    schedule 21.03.2017
comment
@WillemVanOnsem возврат должен быть вне цикла for, я попробовал и теперь получаю 0 вместо None, что все еще неверно   -  person Eve    schedule 21.03.2017
comment
Если это Python 2, то (b-a)/N будет целочисленным делением с округлением до 0 в вашем случае. Используйте float для преобразования a и b в числа. Концептуально - в любом случае это должен быть поплавок. Зачем настаивать на том, что пределы интегрирования являются целыми числами?   -  person John Coleman    schedule 21.03.2017
comment
@JohnColeman это потому, что я использую диапазон, сначала я использовал их как числа с плавающей запятой, но я получаю сообщение об ошибке   -  person Eve    schedule 21.03.2017
comment
N должно быть целым числом, а a, b должно быть числом с плавающей запятой.   -  person John Coleman    schedule 21.03.2017


Ответы (3)


Первой проблемой была переменная h как int, затем цикл до N-1 и после этого return внутри цикла.

def integral(f,a,b,N):
    h = float(b-a)/float(N)
    result = 0.
    result += h*f(a)
    for i in range(1,N):
        result += h*f(a+i*h)
    return result
person sebacastroh    schedule 21.03.2017

for i in range(1, N-1):
    result += h * f(a + i*h)
    return result

Если N = 2, то for i in range(1, 1) не будет выполняться, поэтому integral возвращает None.

Но даже если N > 2, наличие return внутри цикла for не имеет никакого смысла, поскольку будет выполняться только первая итерация, а затем возвращаться то, что есть result.

person DeepSpace    schedule 21.03.2017
comment
Извинения. Иногда трудно угадать, как код мог выглядеть с другой стороны. +1. - person Willem Van Onsem; 21.03.2017

У вас уже есть хороший ответ, но ваш код можно немного улучшить:

Нет причин обрабатывать крайнюю левую конечную точку иначе, чем другие точки выборки. Начиная с a = a + 0, если вы начинаете цикл с i=0, вы выбираете a при первом проходе через цикл:

def integral(f,a,b,N):
    h = (b-a)/float(N)
    result = 0.0
    for i in range(N):
        result += h*f(a+i*h)
    return result

Кроме того, было бы более Pythonic заменить явный цикл, напрямую применяя sum к пониманию:

def integral(f,a,b,N):
    h = (b-a)/float(N)
    return h*sum(f(a + i*h) for i in range(N))

Это функционально то же самое, что и первое определение. Например:

>>> integral(lambda x: x**2,0,1,100)
0.32835000000000003

Наконец, если вы используете Python 2, приведенное выше следует изменить так, чтобы он использовал xrange(), а не range().

person John Coleman    schedule 21.03.2017
comment
Большое спасибо! Еще один вопрос, если вы не возражаете, как бы вы переписали цикл для N, чтобы вместо получения ошибки, если пользователь вводит значение с плавающей запятой, он заставлял пользователя вводить действительный ввод? - person Eve; 22.03.2017
comment
@Eve Вы могли бы использовать что-то вроде N = int(float(input("Enter number of subintervals: "))) - person John Coleman; 22.03.2017
comment
Это решает проблему с ошибкой, но не заставляет пользователя повторно вводить действительный номер. - person Eve; 22.03.2017
comment
@Eve Если вы действительно хотите заставить пользователя ввести int: см. это: stackoverflow.com/q/23294658/4996248 - person John Coleman; 22.03.2017
comment
Мне удалось это сделать, есть ли альтернатива try-кроме хотя? Я пытался написать простой цикл while, используя if-else, но не смог сделать это правильно. Вероятно, это потому, что я пытался проверить, является ли число целым, и сделал это неправильно: if string_input == int. Даже если я введу целое число, цикл не сломается. Есть ли способ сделать это правильно? - person Eve; 22.03.2017