python 要实现所需的浮点结果精度,需要修改代码中的哪些内容?

olmpazwi  于 2023-01-16  发布在  Python
关注(0)|答案(1)|浏览(92)

在阅读麻省理工学院开放式课程习题集的第三部分时,我遇到了一些疑问。问题描述如下:

C部分:找到合适的保存金额:

在B部分,你有机会探索你每月保存的工资百分比和你每年的加薪如何影响你为首付储蓄的时间。这很好,但是假设你想设定一个特定的目标,例如在三年内能够支付首付。你每月应该储蓄多少来实现这个目标?在这个问题中,你要写一个程序来回答这个问题。2为了简化,假设:3
1.你的半年加薪是0.07(7%)
1.您的投资年回报率为0.04(4%)
1.首付款是房价的0.25(25
1.你存钱买房子的费用是100万美元。
你现在要试着找到最佳储蓄率,在36个月内支付100万美元的首付款。因为准确地达到这个目标是一个挑战,我们只希望你的储蓄在所需首付款的100美元以内。在www.example.com中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。

jdgnovmf

jdgnovmf1#

首先,您没有执行浮点优化。即使您在中间步骤中使用浮点运算,您也是以定点格式保存优化变量,因此执行的是定点优化。当您使用整数和常数比例因子(100000)来表示有理数或真实的时,该有理数或实数是定点,而不是浮点。
由于您使用的是固定点值,因此如果您希望确保获得精确到最接近0.0001的结果,只需更改退出条件即可。与其在答案精确到节省的美元数最接近100美元时立即退出,不如等到答案精确到最接近0.0001时再退出。因为您的定点表示法意味着要等到highlow相隔1个计数,然后报告其中一个数字,该数字给出的结果最接近所需的最终节省。
旁注:由于highlow始终是整数,因此可以使用(high+low)//2来使用整数运算,以获得与int((high+low)/2)相同的结果,而无需转换为浮点数并再次转换回来。

相关问题