簡易版複利計算機

因為最近有點沈迷投資理財,
所以想試著寫寫看簡單的複利計算機。
複利基本公式:

 FV = PV ( 1+i )^n\,

FV = Future Value,本利和
PV = Present Value,本金
i = interest,利率
n就是週期

===========================以下為程式碼===========================

import math
print('''
複利基本公示:FV = PV x (1 + i)^n

定期定額公式:FV = PV x {[(1 + i)^n - 1] / i}

FV:Future Value,本利和
PV:Present Value,本金
i :interest,利率
n :週期
''')

while True:
    print('''
=======================分隔線=======================

1. 純複利計算機
2. 定期定額計算機
3. 結束計算機
''')
    temp = input('請輸入運行項目:')

    if temp.isdigit() == True:

        if int(temp) == 1:
            while temp:
                print('''
=======================分隔線=======================

1.計算本利和:須填入「本金」、「年利率」及「期數」。
2.計算本金:須填入「本利和」、「年利率」及「期數」。
3.計算年利率:須填入「本利和」、「本金」及「期數」。
4.計算期數:須填入「本利和」、「本金」及「年利率」。

5.離開純複利計算機。

''')
                item = input('請輸入運行項目:')

                if item.isdigit() == True:
                    if int(item) == 1:
                        PV = int(input('請輸入本金:'))
                        i = int(input('請輸入年利率  %:'))
                        i = i / 100
                        n = int(input('請輸入期數:'))

                        FV = PV*(1 + i)**n
                        print('您的本利和總計為為',FV,'元')

                    elif int(item) == 2:
                        FV = int(input('請輸入本利和:'))
                        i = int(input('請輸入年利率  %:'))
                        i = i / 100
                        n = int(input('請輸入期數:'))

                        PV = FV / ((1 + i)**n)
                        print('您所需要的本金為',int(PV) + 1,'元')
                       
                    elif int(item) == 3:
                        FV = int(input('請輸入本利和:'))
                        PV = int(input('請輸入本金:'))
                        n = int(input('請輸入期數:'))

                        i = ((FV / PV)**(1 / n)) - 1
                        i = int(i * 1000)
                        r = i % 10
                        if r <= 4:
                            i = i / 1000
                            i = i.__round__(2)
                        else:
                            i = int((i / 10)+1)
                            i = i / 100
                        #i = (float('%.2f' % i) + 0.01) * 100
                        print('您所需要的年利率為',i,'%')
                    elif int(item) == 4:
                        FV = int(input('請輸入本利和:'))
                        PV = int(input('請輸入本金:'))
                        i = int(input('請輸入年利率  %:'))
                        i = i / 100

                        n = math.log((FV / PV),(1 + i))
                        n = int(n) + 1
                        print('要達成您的目標需要',n,'年時間。')
                       
                    elif int(item) == 5:
                        break

                else:
                    print('')
                    print('請重新填入正確的項目,謝謝。')
                    continue
                               
        elif int(temp) == 2:
            while temp:
                print('''
=======================分隔線=======================

小提醒:定期定額以「月利率」計算會比「年利率」準確。

1.計算本利和:須填入「本金」、「利率」及「期數」。
2.計算本金:須填入「本利和」、「利率」及「期數」。
3.計算利率:須填入「本利和」、「本金」及「期數」。(暫時無功能)
4.計算期數:須填入「本利和」、「本金」及「利率」。

5.離開定期定額計算機。

''')
                item = input('請輸入運行項目:')

                if item.isdigit() == True:
                    if int(item) == 1:
                        PV = int(input('請輸入本金:'))
                        i = int(input('請輸入利率  %:'))
                        i = i / 100
                        n = int(input('請輸入期數:'))

                        FV = PV*((((1 + i)**n)-1)/i)
                        print('您的本利和總計為為',FV,'元')

                    elif int(item) == 2:
                        FV = int(input('請輸入本利和:'))
                        i = int(input('請輸入利率  %:'))
                        i = i / 100
                        n = int(input('請輸入期數:'))

                        PV = FV / ((((1 + i)**n)-1)/i)
                        print('您所需要的本金為',int(PV) + 1,'元')
                       
                    elif int(item) == 3:
                        #FV = int(input('請輸入本利和:'))
                        #PV = int(input('請輸入本金:'))
                        #n = int(input('請輸入期數:'))

                        #i = ((FV / PV)**(1 / n)) - 1
                        #i = (float('%.2f' % i) + 0.01) * 100
                        #print('您所需要的利率為',i,'%')

                        print('都說了暫時無功能還點進來= =')
                        print('作者數學不好寫不出來,請耐心等待下一版')
                        continue
                       
                    elif int(item) == 4:
                        FV = int(input('請輸入本利和:'))
                        PV = int(input('請輸入本金:'))
                        i = int(input('請輸入利率  %:'))
                        i = i / 100

                        n = math.log(((FV / PV)*i)+1,(1 + i))
                        n = int(n) + 1
                        print('要達成您的目標需要經過',n,'個時間單位。')
                       
                    elif int(item) == 5:
                        break

                else:
                    print('')
                    print('請重新填入正確的項目,謝謝。')
                    continue
        elif int(temp) == 3:
            print('謝謝光臨,歡迎再次使用。')
            break
    else:
        print('')
        print('請重新填入正確的項目,謝謝。')
        continue

===========================以上為程式碼===========================

大致上除了探索數學公式比較困擾之外沒什麼問題。
但在寫計算機的過程當中,
倒是遇到了「如何取小數點精度並四捨五入」的問題。

方法一:使用round函數
如:round(37.452, 2)
>>> 37.45
round(37.458, 2)
>>>37.46
但是round函數其實不是採用四捨五入的規則。
參考這篇文章

round()如果只有一個數作為參數,不指定位數的時候,返回的是一個整數,而且是最靠近的整數(這點上類似四捨五入)。但是當出現.5的時候,兩邊的距離都一樣,round()取靠近的偶數,這就是為什麼round(2.5) = 2。當指定取捨的小數點位數的時候,一般情況也是使用四捨五入的規則,但是碰到.5的這樣情況,如果要取捨的位數前的小樹是奇數,則直接捨棄,如果偶數這向上取捨。

 所以在某些情況下用round函數會失準,
應該要找其他的手法。

方法二: 使用字符串格式化



>>> '%6f' % 4.58  #欄位寬度6
>>> '4.580000'
>>> '%6.3f' % 4.58  #欄位寬度6, 精度3
>>> ' 4.580'  #注意,前面有個空格哦
>>> '%.3f' % 4.58  #精度3
>>> '4.580'

但是這個方法的行為模式和round函數基本上完全相同,
所以還是要再找更精準的做法。

方法三:轉換成int後再計算,算完再轉換成float
參考這篇文章

最保證正確但很笨的方法

應該是在存儲的時候保存為int

比如 例子的17.955

應該保存為 17955 小數部分長度 3

你要保留2位有效數字就是 取決於最後一位, 所以要除以 10

17955 除以 10 得到 1795 餘數 5

餘數 5 大等於 5 所以商要加1

(1795+1)*10 就還原成想要的int 然後再除以 1000 就得到想要的 float

這其實是在用二進位類比十進位的演算法

 就夠精準了!

 ================================碎念分隔線 ================================

沒有料到一個四捨五入要這麼搞剛......

留言

這個網誌中的熱門文章

零基礎入門學習python_003筆記及作業_字串與轉譯

哈佛大學計算機通識課程:CS50