[英]What needs to be modified in the code to achieve a desired accuracy of floating point result?
在处理麻省理工学院 OCW 问题集中的一个问题的第三部分时,我遇到了一些疑问。 问题描述如下:
第 C 部分:找到合适的储蓄金额:
在 B 部分,您有机会探索每月储蓄的工资百分比和年度加薪如何影响您为首付款储蓄的时间。 这很好,但是假设您想设定一个特定的目标,例如能够在三年内负担得起首付。 为了实现这一目标,您每个月应该存多少钱? 在这个问题中,您将编写一个程序来回答该问题。 为简化起见,假设:3
- 你的半年加薪是.07 (7%)
- 您的投资年回报率为 0.04 (4%)
- 首付款为房屋成本的 0.25 (25%)
- 您要存钱买的房子的成本是 100 万美元。
您现在要尝试找到最佳储蓄率,以便在 36 个月内支付 100 万美元房屋的首付。 由于准确地达到这个目标是一项挑战,我们只是希望您的储蓄在所需首付款的 100 美元以内。 在ps1c.py中,编写程序计算最佳储蓄率,即你的起薪为function。 您应该使用二分搜索来帮助您高效地执行此操作。 您应该跟踪完成二分搜索所需的步骤数。 您应该能够在此问题中重用您为 B 部分编写的一些代码。 因为我们正在搜索原则上是浮点数的值,所以我们将把自己的精度限制在小数点后两位(即,我们可能希望节省 7.04% 或小数点后的 0.0704——但我们不会担心7.041% 和 7.039% 之间的差异)。 这意味着我们可以在 0 和 10000 之间搜索一个 integer(使用 integer 除法),然后将其转换为小数百分比(使用浮点除法)以在计算 36 个月后的 current_savings 时使用。 通过使用这个范围,我们只搜索有限数量的数字,而不是 0 到 1 之间的无限小数。这个范围将有助于防止无限循环。 我们使用 0 到 10000 的原因是为了在 0% 到 100% 的范围内占两个额外的小数位。 您的代码应打印出一个小数点(例如,0.0704 表示 7.04%)。
后面的问题描述清楚地指出,可以通过在不同的 styles 中实施二分搜索,以各种不同的方式解决这个问题,这最终会给出不同的结果,而且它们都是正确的,即,有多种速率可以节省大约是首付款的 100。 然而,问题的解决方案不再是我关心的,因为我意识到我已经解决了它; 我现在想知道的是我必须对我的代码进行哪些修改,以便我可以生成与下面提供的预期测试 output 相似精度的输出:
测试用例 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。
首先,您没有进行浮点优化。 即使您对中间步骤使用浮点运算,您也在以定点格式保存优化变量,因此进行定点优化。 当您使用 integer 和常数比例因子 (100000) 表示定点而非浮点的有理数或实数时。
由于您使用的是固定点值,如果您想确保获得精确到最近的 .0001 的结果,您只需更改退出条件即可。 不要在您的答案正确到最接近的 100 美元(以节省的美元计算)时立即退出,而是等到答案正确到最接近的 .0001 作为薪水的一小部分。 其中,由于您的固定点表示意味着等到high
点和low
被 1 个计数分开,然后报告数字中的任何一个给出最接近所需最终节省的结果。
旁注:由于high
和low
始终是整数,您可以使用(high+low)//2
来使用 integer 操作以获得与int((high+low)/2)
相同的结果,而无需转换为浮点数并再次返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.