定期產品如何用活期的方式展示——逼近演算法
這篇文章是我分享PPT內容的總結,主要講述如何使用逼近演算法解決工作中的一些棘手問題,通過解決具體場景的問題進行分析。
前序:演算法是什麼
演算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。簡單而言演算法就是解決問題的步驟,其特徵:
1,有窮性(Finiteness):演算法的有窮性是指演算法必須能在執行有限個步驟之後終止;
2,確切性(Definiteness):演算法的每一步驟必須有確切的定義;
3,輸入項(Input):一個演算法有0個或多個輸入,以刻畫運算物件的初始情況,所謂0個輸入是指演算法本身定出了初始條件;
4,輸出項(Output):一個演算法有一個或多個輸出,以反映對輸入資料加工後的結果。沒有輸出的演算法是毫無意義的;
5,可行性(Effectiveness):演算法中執行的任何計算步驟都是可以被分解為基本的可執行的操作步,即每個計算步都可以在有限時間內完成(也稱之為有效性)。
程式=資料+邏輯(演算法),任何簡單或者複雜的演算法都可以由順序結構、選擇結構和迴圈結構這三種基本結構組合而成。所以這三種結構被稱為程式設計的三種基本結構,也是程式化程式設計必須採用的結構。
在編寫PPT的時候,我曾想如何能夠生動形象的講明白講清楚一件事?思來量去,覺的按照一條線來比較清晰。於是用了我處理的思路流程,也是這篇文章的各個大綱:遇到問題——》分析問題——》解決問題——》思考問題——》延伸問題——》昇華問題。好,下邊具體講講各個階段的思考。
一,業務場景是什麼?
這裡以金融P2P為背景:
定期理財常見業務型別:到期一次性還本付息、按月等額本息、按月等額本金,其中各類的計算公司方法如下:
1,到期一次性還本付息:
2.1,按月等額本息總金額計算:
2.2,按月等額本息每期還款本金計算:
3.1,按月等額本金計算:
定期業務中的各種計算方法,都是按照本金,計算了用於一段固定時間的利息,如果想要轉化計算出使用者每天得到的利息呢?
一方案是利用單利計算方法,簡單將使用者這段時間應得的利息除於時間段的天數,得到每天的利息。這種方案是使用者體驗度特別差,而且不夠合理,因為每天增加利息一樣,今天應得的利息,不是按照昨天的本息和計算,而是按照最初的本金計算,不合理。
二方案是利用複利計算(日、月、年複利)方法,這種方案是使用者今天應得利息,是按照昨天的本息和進行計算,使用者的日利息是每天不斷增加的,合理。
好,場景就是利用方案二,根基定期業務的本息值,來計算出使用者的日利息(類似活期的計算方式),而計算使用者日利息就需要計算準確的日複利利率。
二,業務實現難點?
如何將定期計算方式和活期計算方式進行等價(定期≈活期)
推導最複雜的對按月等額本息轉化活期求日複利利率的公司,根據經典的PMT公式進行推導得:
還款額/(1+x)^n1+還款額/(1+x)^n2+還款額/(1+x)^n3+……=本金(x為日利率,n表示每期還款日距起息日的天數)
難點就是如何進行公式求解,求出x日利率。
三,實現方案有哪些?
1,對公式進行推導、反解出x日複利利率=某個公式(因為涉及到分母的不同次冪,所以很難,或者沒有,大家可以嘗試嘗試);
2,EXCEL單變數求解(工具、理論),求出來(EXCEL功能還是非常強大的),對每月天數進行四捨五入,進行配置(有誤差、可實現);
3,逼近法:根據起息日和還款額計算出日複利利率,通過探測的方法,試出來,利用計算機善於做有規則、重複的功能,通過X的不斷試值,來達到一個我們滿意的結果(例如誤差在百萬分之一、千萬分之一、億分之一……)(效能控制:需要考慮這個演算法對時間複雜度和空間複雜度測試評估);
探索的過程:1,首先直接去解前邊的方程(通過各種數學方法,百度也好,問別人也好,自己探索也好);2,轉變思路,為了實現業務,善假於物也;3,為了追求完美,找到逼近演算法;
好,下來我們來看看逼近演算法,逼近演算法,顧名思義就是通過嘗試不斷靠近正確答案的一種演算法。在數學中,數值逼近是研究函式的離散逼近,用適合於計算機上的計算的簡單函式(如多項式,連分式等)逼近複雜函式。主要包括插值法、最佳一致逼近、最佳平方逼近與最小二乘逼近。其中的難點就是初始值的設定、步長的設定,逼近的策略(設定到逼近的次數,這個必須在可控制之內,在計算機效能之內),誤差的數量級控制等。
好,下邊看最簡單的兩種逼近,大家看下那個更好一些:
/**
* 逼近法求日利率
*
* @param info PMT公司計算的還款計劃,
* @param contractAmount 起息金額
* @return
*/
public static double getExpectDateRate(HashMap info[], double contractAmount) {
double step = 0.00000001d;
double der = 1.000028d;
double n, repay;
int interval_value_date;
do {
der = new BigDecimal(step + der).setScale(8, BigDecimal.ROUND_HALF_UP).doubleValue();
n = repay = 0.0;
interval_value_date = 0;
for (int i = 0; i < info.length; i++) {
repay = (Double) (info[i].get("repay"));
interval_value_date = (Integer) (info[i].get("interval_value_date"));
n += repay / Math.pow(der, interval_value_date);
}
} while (n > contractAmount);
return new BigDecimal(der).setScale(8, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 等額本息逆推實際利率法
*
* @param Principal 本金
* @param MonthlyPayments 月還款額
* @param Period 期數
* @param Iterations 運算次數
* @param Digit 保留位數
* @return 利率
* @author ljh
*/
public static Double getYearRate(Double Principal, Double MonthlyPayments, int Period, int Iterations, int Digit) {
double rate = 1, x, jd = 0.1, side = 0.1, i = 1;
do {
x = Principal / MonthlyPayments - (Math.pow(1 + rate, Period) - 1) / (Math.pow(rate + 1, Period) * rate);
if (x * side > 0) {
side = -side;
jd *= 10;
}
rate += side / jd;
} while (i++ < Iterations && Math.abs(x) >= 1 / Math.pow(10, Digit));
if (i > Iterations) {
return Double.NaN;
}
return rate;
}
四,思考總結:
1,為什麼簡單的重複計算卻解決了我們的難題?
2,需要考慮什麼:時間複雜度、空間複雜度
3,這種演算法模型的使用場景?
五,其它方面的運用?
這裡簡單說下最近比較火的AI。神經網路有input資料入口,Hidden演算法結構,output輸出結果,通過反向傳播訓練演算法結構的引數,然後利用正向傳播進行預測等。其中得到最優演算法結構的引數很多演算法都是通過大資料量、高重複計算,不斷慢慢逼近得到的。只不過在AI的運用更加複雜而已。
六,思考昇華更大的為什麼?
1,問題——》目標的道路?
2,解決問題的道路都是想通的?
3,解決問題都是都非常簡單?
4,解決問題都是非常難?
好,後邊幾個方面其實比較發散,由於是PPT的總結,這裡大家仁者見仁智者見智,沒有什麼誰更對,只要思考這些問題,或者更多的問題就OK。