[英]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.