# 计导第四次作业 (Past)

10205102406 edited 2 年，1 月前

This is a past version of blog 计导第四次作业

1、（20 pointsLet ID=your student ID. Then, let k=ID %2. So k can be 0 or 1. Based on the value of your ID, you get value of k. Please tell us your k value.

If k==0: 做《计算机导论》练习题2.2.1 2.2.3 2.2.5**2.2.7, 2.2.9, 2.2.11

If k==1: 做《计算机导论》练习题*2.2.2 2.2.4* 2.2.6*，2.2.8, 2.2.10. 2.2.12*

def shift(n, k):
res = ""
while(n != 0):
a = n%k
n //= k
if(a<10): res += str(a)
else: res += chr(55+a)
return res[::-1]

print("2.2.1", shift(78,2))
print("2.2.3", shift(358,16),shift(358,8))
print("2.2.5", 10*16**3+10*16**2+0+12)
print("2.2.7", "B")
print("2.2.9", 149.4375, 1205.6)
print("2.2.11", 8, 201)


2、（10 points）《计算机导论》程序练习2.2.1,

def shift(n, k):
res = 0
for i in n:
res *= k
if i != '0':
res += int(i)
return res

n = input("n:")
k = int(input("k:"))
print(shift(n, k))


3、（10 points）《计算机导论》程序练习2.2.2

def shift(n, k):
res = ""
while(n != 0):
a = n%k
n //= k
res += str(a)
return res[::-1]

n = int(input("n:"))
k = int(input("k:"))
print(shift(n, k))


4、（15 points）这题可以两人合作，写下合作同学的名字及学号。《编程导论》老虎机游戏的练习题2.5.4

import random

def tiger(money, k):
count = 0
while money > 0 and count != k:
money -= 1
r = random.random()
if r < 0.6:
prize = 0
elif r < 0.8:
prize = 1
elif r < 0.9:
prize = 2
else:
prize = 3
money += prize
count += 1
return count,money

print("在第%d轮结束，剩余：%d"%tiger(10,10))
print("在第%d轮结束，剩余：%d"%tiger(10,20))
print("在第%d轮结束，剩余：%d"%tiger(10,30))
print("在第%d轮结束，剩余：%d"%tiger(10,40))


import random

def tiger(money):
m = money
while m > 0:
m -= 1
r = random.random()
if r < 0.6:
prize = 0
elif r < 0.8:
prize = 1
elif r < 0.9:
prize = 2
else:
prize = 3
m += prize
if(m > money):
return 1
return 0

count = 0
for i in range(100):
count += tiger(10)
print(count)


5、（15 points）《编程导论》2.4节讨论for循环，（A）请说明Pythonfor i in range(a,b,step)的循环结构和C语言的 for(i=a; i的差异？（*B）解释for i in range(len(L)),* i=0; while ii+=1 结构的差异？（C）解释for e in LL是一个列表）是如何遍历的？假设L在循环中被改变了，接下去是新列表还是旧列表被遍历？它比较像for i in range(len(L)), 还是 while i结构**?

A 首先，python中不需要提前创建变量i，而该c语句则需要在之前先定义i；其次，python实际上是遍历了range函数产生的list，会有额外的消耗，而c则确实是每次改变i，只需要常数空间；但同时，python不会在循环体中改变i，但c可以，甚至可以改变b和step，而python不可以。
B 首先，for循环的range产生list占用了空间，而while则是常数空间；其次while中i和len（L）可以改变，for中则不行。
C 从首个元素开始顺序遍历L。不一定，这取决于对L的改变是发生在原地址空间还是将新的列表赋值给变量L。我觉得像for。

6、（10 points）《编程导论》习题2.14。请不要用递归完成此程序。我们以后考试时可能会问你此题如何用递归完成，但是现在请不用。

def merge(L1, L2):
res = []
if len(L1) == 0:
return L2
elif len(L2) == 0:
return L1

a = 0
b = 0

while(a<len(L1) and b<len(L2)):
if(L1[a]>L2[b]):
res.append(L2[b])
b+=1
else:
res.append(L1[a])
a+=1

while(a<len(L1)):
res.append(L1[a])
a += 1

while (b < len(L2)):
res.append(L2[b])
b += 1

return res

print(merge([1,4,7],[2,5]))
print(merge([1,2,3],[]))


7、这题可以两人合作，写下合作同学的名字及学号。请同学们把你的代码拷贝到word报告中，并将程序的运行结果截图粘贴到代码下方。

a） 5 points）使用等额本息方式，请推导并说明每月还款金额的公式，请自行到网上探索；

b） 10 points）编写Python程序，假设贷款的本金为80万，年利率6%（月利率是它的1/12），贷款30年，（1）求出每月还款金额；（2）列出每年归还的本金及利息，以及全部交付的本金及利息；想想为什么要付这么多的利息啊？你大舅问你是不是前几年付的钱大部分都是付给利息啊？

def pay(A,r,n):
t = (1+r)**n
return A*r*t/(t-1)

A = 800000
r = 0.005
n = 360
rp1 = 1+r
paid_principal_sum = 0
paid_interest_sum = 0

average = pay(A,r,n)
for i in range(0,360):
paid_interest = A * r
A = A * rp1 - average
paid_principal = average - paid_interest
paid_principal_sum += paid_principal
paid_interest_sum += paid_interest
print("当前是第%d年第%d月，支付本金：%f，利息：%f"%(i//12+1, i%12+1, paid_principal, paid_interest))
print("共支付本金:%f,利息%f" %(paid_principal_sum, paid_interest_sum))


c） 5 points）重复前面题目b)，但是贷款期限为20年；利息是不是少了很多？

d） 10 points）大舅为了要节省利息，所以想早点还款，如前所述，贷款期限为20年，但是在第三年结束时大舅提前多归还银行本金20万（注意是本金），注意这个时候大舅归还了3年原来每月还的本金部分和额外的20万本金。若以后每月还款金额维持原状（最后一个月还款数可以较少），那么本来需要240个月还清的贷款，现在需要多少个月还清？不准用log在公式上计算。

def pay(A,r,n):
t = (1+r)**n
return A*r*t/(t-1)

A = 800000
r = 0.005
n = 240
rp1 = 1+r
paid_principal_sum = 0
paid_interest_sum = 0

average = pay(A,r,n)
for i in range(0,36):
paid_interest = A * r
A = A * rp1 - average
paid_principal = average - paid_interest
paid_principal_sum += paid_principal
paid_interest_sum += paid_interest
print("当前是第%d年第%d月，支付本金：%f，利息：%f"%(i//12+1, i%12+1, paid_principal, paid_interest))
print("共支付本金:%f,利息%f" %(paid_principal_sum, paid_interest_sum))

A -= 200000
print(A)
i = 37
while(A>average):
paid_interest = A * r
A = A * rp1 - average
paid_principal = average - paid_interest
paid_principal_sum += paid_principal
paid_interest_sum += paid_interest
print("当前是第%d年第%d月，支付本金：%f，利息：%f" % (i // 12 + 1, i % 12 + 1, paid_principal, paid_interest))
i+=1
print("共支付本金:%f,利息%f" % (paid_principal_sum, paid_interest_sum))
print("现在是第%d月,剩余%f，本月底可付清"%(i,A))


e） 10 points）另外一种贷款计算方式叫做“等额本金”，请到网上查询。请以20年贷款80万，年利率6%为例，为简单起见，以“月”为单位，不以“天”为单位，请编程计算出使用等额本金方式所支付的利息总数，以及列出前12个月每月所还的金额，并且请从利息的角度说明它与等额本息的差异，请分析两者，等额本息和等额本金，的优劣，为什么现在银行都喜欢用等额本息方式来计算贷款？

A = 800000
r = 0.005
n = 240
rp1 = 1+r
paid_interest_sum = 0

base = A/n
for i in range(n):
interest = (A-base*i)*r
paid_interest_sum+=interest
if(i<12):
print("第%d月支付：%f" %(i+1,interest+base))
print("总利息：%f"%paid_interest_sum)