我试图递归计算数组中5个数字的总和。但是,我从递归函数得到的输出为0。如果我取消注释print语句,则得到的总和为15,但函数返回的总和为0。在这里我在做什么错??
我的代码-
def calcsum(arr):
i = 0
sum = 0
solution(arr,sum,i)
return sum
def solution(arr,sum,i):
if i == len(arr):
return
sum = sum + arr[i]
#print(sum,i)
solution(arr,sum,i+1)
print(calcsum([1,2,3,4,5]))
答案 0 :(得分:1)
请记住,递归至少有两种情况:
无论哪种情况您都不会返回值!尝试以下方法:
def solution(arr, sum_, i):
if i == len(arr):
return sum_
sum_ += arr[i]
return solution(arr, sum_, i+1)
此外,仅调用solution
不会更改sum
中calcsum
的值,因此return sum
将始终给出0
。请尝试:
def calcsum(arr):
return solution(arr, 0, 0)
(顺便说一句,在这种构造中,您创建了一个函数,该函数使用一些添加的参数将调用委托给助手,这使我想起了很多Haskell,您可能会在其中写:
calcsum :: Num a => [a] -> a
calcsum = go 0 0
where go :: Num a => Int -> Int -> [a] -> a
go acc idx xs
| length xs >= idx = acc
| otherwise = go (acc + (xs !! idx)) idx+1 xs
您的逻辑也有些混乱。考虑使用类似的东西:
def solution(arr):
if arr:
# Recursive case
x, rest = arr[0], arr[1:]
return x + solution(rest)
else:
# Base case
return 0
现在的基本情况是arr
为空(而不是传递数组外部的索引时)。您计算空列表的总和,该列表只能在逻辑上由0
来计算。递归情况将第一个元素从列表中拉出,并将其添加到列表其余部分的解决方案中。
答案 1 :(得分:1)
如前所述,您应该返回总和。这是迭代器版本:
def calcsum(arr):
return solution(iter(arr), 0)
def solution(it, sum):
for x in it:
return solution(it, sum + x)
return sum
print(calcsum([1,2,3,4,5]))
仅使用一个函数和一个参数的更短的方式,在递归后添加x
:
def calcsum(it):
it = iter(it)
for x in it:
return x + calcsum(it)
return 0
print(calcsum([1,2,3,4,5]))
两个解决方案都需要线性时间,而类似的解决方案只需要arr
并将其拆分为arr[0]
和arr[1:]
,这需要整个二次时间。通过汇总1000个值的列表来比较该迭代器版本与该列表版本的基准:
0.28 ms calcsum_1
2.70 ms calcsum_2
基准代码:
from timeit import repeat
def calcsum_1(it):
it = iter(it)
for x in it:
return x + calcsum_1(it)
return 0
def calcsum_2(arr):
if arr:
x, rest = arr[0], arr[1:]
return x + calcsum_2(rest)
return 0
arr = [1] * 1000
for _ in range(3):
for f in calcsum_1, calcsum_2:
t = min(repeat(lambda: f(arr), number=1000))
print('%.2f ms ' % t, f.__name__)
print()
答案 2 :(得分:1)
您的代码至少有五个问题:
solution(arr, sum, i)
中对calcsum
的调用不会修改calcsum
的局部变量sum
,因此calcsum
始终返回0; return
中的递归写了return sum
而不是solution
,所以solution
将返回None
而不是返回总和这种情况solution(arr,sum,i+1)
而不是return solution(arr,sum,i+1)
或some_variable = solution(arr,sum,i+1)
,所以递归调用的返回值还是会被忽略。除了return
块内的语句之外,没有if
语句,因此函数solution
将没有返回值(或更准确地说,它将返回None
); sum
中的solution
会修改整个程序中称为sum
的任何变量。错了sum
是函数的局部变量,对其进行修改不会影响程序的其余部分。sum
是一个坏主意;这是内置函数的名称,因此您应该尝试为变量找到另一个名称。为说明第四点,请尝试以下代码:
def mostly_harmless(n):
n = 7
n = 8
mostly_harmless(n)
print('Does this set n to 7? Am I about to print 8 or 7?')
print(n)
print()
mostly_harmless(12)
print('did we set 12 = 7? did we just break all of mathematics?')
print('making sure 12 is still 12:')
print(12)
print('making sure n is still n:')
print(n)
考虑到这一点,我们可以修复您的代码:
def calcsum(arr):
return solution(arr, 0, 0)
def solution(arr, sum, i):
if i == len(arr):
return sum
else:
return solution(arr, sum + arr[i], i+1)
print(calcsum([1,2,3,4,5]))
实际上,我们可以使用默认参数进一步简化代码:
def calcsum(arr, sum=0, i=0):
if i == len(arr):
return sum
else:
return calcsum(arr, sum + arr[i], i+1)
print(calcsum([1,2,3,4,5]))
但是请注意,python是不是的一种喜欢递归的语言。在其他一些编程语言中,递归非常好,并且与循环和while循环一样高效。但这不是python中的情况。在python中,递归比循环慢得多,并且使用更多的内存。我们可以使用for循环来重写您的程序:
def calcsum(arr):
sum = 0
for i in range(len(arr)):
sum += arr[i]
return sum
print(calcsum([1,2,3,4,5]))
甚至更好:
def calcsum(arr):
sum = 0
for v in arr:
sum += v
return sum
print(calcsum([1,2,3,4,5]))
还要注意,在python中调用变量sum
是一个坏主意,因为sum
是python中内置函数的名称。您可以在the python documentation中找到内置的列表;尝试为您的变量命名。
毫不奇怪,函数sum
本身就可以计算总和:
print(sum([1,2,3,4,5]))
那么为什么调用变量sum
如此糟糕呢?好吧,那么我们将无法使用相同名称的内置函数:
sum = 7
print(sum([1,2,3,4,5]))
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: 'int' object is not callable
通常sum
指的是内置函数;但现在它引用的变量等于7
;当我尝试调用sum([1,2,3,4,5])
时,就好像我尝试调用7([1,2,3,4,5])
一样,这没有意义,因为7
不是函数。
答案 3 :(得分:1)
您可以使其“按自己的方式”工作,即,如果将sum
放在变量calcsum
中并增加其外部solution
,则可以增加sum
中的arr
变量而不是拥有自己的。然后也不需要通过def calcsum(arr):
def solution(i):
nonlocal sum
if i == len(arr):
return
sum = sum + arr[i]
solution(i+1)
sum = 0
solution(0)
return sum
print(calcsum([1,2,3,4,5]))
。
public partial class frmMain : Form
{
SqlConnection connectionsql;
string connectionString;
public frmMain()
{
InitializeComponent();
connectionString = ConfigurationManager.ConnectionStrings["Equipment_Inventory.Properties.Settings.InventoryConnectionString"].ConnectionString;
}
private void frmMain_Load(object sender, EventArgs e)
{
populategrid();
}
private void populategrid()
{
using (connectionsql = new SqlConnection(connectionString))
using(SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Inventory", connectionsql))
{
DataTable InventoryTable = new DataTable();
adapter.Fill(InventoryTable);
dataGridView1.DataSource = InventoryTable;
}
}
private void insert_button(object sender, EventArgs e)
{
string query = "insert into Inventory (InternalNumber, Grupa, Type, Manufacturer, Equipment) values (@InternalNumber, @Grupa, @Type, @Manufacturer, @Equipment)";
using (connectionsql = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connectionsql))
{
connectionsql.Open();
command.CommandType = CommandType.Text;
command.Parameters.Add("@InternalNumber", textBox1.Text);
command.Parameters.Add("@Grupa", textBox2.Text);
command.Parameters.Add("@Type", textBox3.Text);
command.Parameters.Add("@Manufacturer", textBox4.Text);
command.Parameters.Add("@Equipment", textBox5.Text);
command.ExecuteNonQuery();
populategrid();
}
}
}
}