需要在代码中修改什么以实现浮点结果的期望精度



在研究麻省理工学院OCW问题集中的一个问题的第三部分时,我遇到了一些疑问。问题描述如下:

第C部分:找到合适的储蓄金额:

在B部分中,你有机会探索你每月节省的工资百分比和年度加薪如何影响你为首付节省的时间。这很好,但假设你想设定一个特定的目标,例如能够在三年内支付首付。为了实现这个目标,你每个月应该存多少钱?在这个问题中,你将编写一个程序来回答这个问题。为了简化,假设:3

  1. 你每半年加薪0.07(7%)
  2. 您的投资年回报率为0.04(4%)
  3. 首付款是房屋成本的0.25(25%)
  4. 你为这所房子存的钱是100万美元

您现在要尝试找到最佳的储蓄率,以便在36个月内为100万美元的房子支付首付。既然做到这一点是一个挑战,我们只希望您的储蓄在所需首付款的100美元以内。在ps1c.py中,编写一个程序,根据你的起薪计算最佳储蓄率。你应该使用平分搜索来帮助你有效地做到这一点。您应该记录完成平分搜索所需的步骤数。在这个问题中,您应该能够重用为B部分编写的一些代码。因为我们正在搜索一个原则上是浮点的值,所以我们将把自己的精度限制在两位小数(即,我们可能想在小数中节省7.04%或0.0704,但我们不必担心7.041%和7.039%之间的差异)。这意味着我们可以搜索0到10000之间的整数(使用整数除法),然后将其转换为十进制百分比(使用浮点除法),以便在36个月后计算current_savings时使用。通过使用这个范围,我们只搜索有限数量的数字,而不是0到1之间的无限小数。此范围将有助于防止无限循环。我们使用0到10000的原因是为了说明在0%到100%范围内的两个额外的小数点。您的代码应该打印出一个小数(例如,0.0704表示7.04%)。

问题描述稍后明确指出,通过以不同的风格实现平分搜索,可以以各种不同的方式解决这个问题,最终会得到不同的结果,而且这些结果都是正确的,即有多种费率可以节省约100的首付。然而,问题的解决方案不再是我所关心的,因为我意识到我已经解决了它;我现在想知道的是,我必须对我的代码进行哪些修改,这样我才能产生与下面提供的预期测试输出具有相似精度的输出:

测试用例1

>>> Enter the starting salary: 150000
Best savings rate: 0.4411
Steps in bisection search: 12

这是我的问题解决方案:

def calc_savings(startingSalary:int, nummonths:int, portion:float):
"""
Calculated total savings with fixed annual raise and r.o.i for x no. of months 
at 'portion' percentage of salary saved every month.
"""
savings = 0
salary=startingSalary
for months in range(1, nummonths+1):
savings+= (salary/12*portion)+(savings*(0.04/12))
if months%6==0:
salary = salary+(0.07*salary)
return savings
cost = 1_000_000
downpayment = cost*0.25
startingsalary = int(input("Enter starting salary: "))
step = 0
high = 10000
low = 0
if startingsalary*3 < downpayment:
print("Saving the down payment in 36 months with this salary is not possible.")
else:
while True:
portion = int((high+low)/2)/10000
current_savings=calc_savings(startingsalary, 36, portion)
if downpayment - current_savings < 100 and downpayment-current_savings>=0:
break
elif downpayment-current_savings>=100:
low = portion*10000
step+=1
elif downpayment-current_savings < 0:
high = portion*10000
step+=1
print(f"Best savings rate: {portion}")
print(f"Steps in bisection search: {step}")

这就是我得到的结果:

>>> Enter the starting salary: 150000
Best savings rate: 0.441
Steps in bisection search: 12

我意识到这与我为平分搜索选择极限的方式有关,也与我后来如何将从中得到的结果转换回所需的有效位数有关。

在对代码玩了一段时间后,我意识到我的结果中的有效位数与预期结果相同,我通过将月数从36改为40来测试这一点,并得出它是0.441,因为它实际上是0.4410,非常接近0.4411。

我只是想知道我是否可以对我的代码做些什么来达到0.4411。

首先,您不是在进行浮点优化。即使在中间步骤中使用浮点运算,也会将优化变量保存为定点格式,从而进行定点优化。当您使用整数和常数比例因子(100000)来表示有理数或实数时,它是定点,而不是浮点。

由于您使用的是固定点值,如果您想确保得到精确到0.0001的结果,您只需更改退出条件。不要在你的答案正确到100美元(以节省的美元计)后立即退出,而是等到答案正确到0.0001美元(以工资的一小部分计)。由于您的固定点表示,这意味着等待highlow被1个计数分隔开,然后报告其中任何一个数字的结果最接近所需的最终节省。

旁注:由于highlow始终是整数,因此可以使用(high+low)//2使用整数运算来获得与int((high+low)/2)相同的结果,而无需转换为浮点值并再次返回。

相关内容

  • 没有找到相关文章

最新更新