class InterestRateService
{
private $precision = 0.001; //夹逼准则 精度范围
private $principal = 0; //本金
private $flow = []; //还款数据
private $payment_method = 0; //还款方式 0按月还款 1按年还款
private $i = 100; //最大循环次数
public static function getInstance()
{
return new self();
}
/**
* @param $principal//本金
* @param array $flow//还款数据
* @param int $payment_method//还款方式 0按月还款 1按年还款
*
* @return $this
*/
public function setPrecision($principal, $flow = [], $payment_method = 0)
{
$this->principal = $principal;
$this->flow = $flow;
$this->payment_method = $payment_method;
return $this;
}
/**
* irr利率计算.
*
* @return string
*/
public function irrCalculate()
{
$principal = $this->principal;
$precision = $this->precision;
$i = $this->i;
$flow = $this->flow;
$net_present_value = 1;
$min = -10;
$max = 10;
$guess = 0;
$k = 0;
while (abs($net_present_value - $principal) > $precision && $k <= $i) {
++$k;
$net_present_value = 0;
$guess = ($min + $max) / 2;
foreach ($flow as $period=>$cash_flow) {
$net_present_value += $cash_flow / pow(1 + $guess, $period + 1);
}
if ($net_present_value - $principal > 0) {
$min = $guess;
} else {
$max = $guess;
}
}
return ($guess * 100) . '%';
}
/**
* 还款数据返回.
*
* @return array
*/
public function remainingAmount()
{
$principal = $this->principal;
$flow = $this->flow;
$array = [];
foreach ($flow as $i=>$value) {
$array[] = [
'key' => $i + 1,
'money'=> $value,
'left' => $principal - $value,
];
$principal = $principal - $value;
}
return $array;
}
/**
* apr利率计算.
*
* @return string
*/
public function aprCalculate()
{
$periods = $this->getPeriods();
$principal = $this->principal;
$flow = $this->flow;
return (((array_sum($flow) - $principal) / $principal) / ($periods / 12) * 100) . '%';
}
/**
* @return float|int
*/
private function getPeriods()
{
if (0 == $this->payment_method) {
//按月还款
return count($this->flow);
}
return 12 * count($this->flow);
}
}