nfTlWNl rn Ѻq$³*%yNk9SVBŹ!SRbRBlThqi`P{a*`( CӝINgþq ] OEa3dEwԞX^\`Lٔ*ܝIc3ٿ ZmW!@bd.zA , s8"`ޓiҍZi_#1Iķխ}`[W">/m6a7{K]}eЄe#2 ` d$knV)=} Ѻq$³*%yNk9Sz ] 𓼾,_NgU,Z <}pܔL}_?4kCD` _+|dgq>Thp뭻'e`NZ=pj[6GN؂R ->yhWu#%.6msnf:Nͽ,9!:!<5R~nq+c}4GQ U;9j,-h7? \$+!z=RUbڝ{BU-=q9)\hJu\.wvs'q%@(YًyT4E:*X|\^\GWFJǶ7= +\B9uGǙ%k*Y5j~V?۫עH /|D}}VP)sxBT4aUy X Ooe&3 I]C63 ĢQ$3Ch3t}oXuT8Oj0ߒB]svX )-"U&ׇWxIG%!1cAuk4zA ĢQ$3ړ/\Sbm&MS`ᝅ`n ?Ǧij2gqM Fc2pgOw(j܁1B)o2&D iy,!ܤHtH8N xj2Tmh8] l;DRW"Wj Lj(<.񌮞 %! ĢQ$3_Ԅ窨]|1X≕=`ɕGsDP">SK?HN&rR.SfBS|w4.llPQܥ%%ד!{n 7Le>=blu, RXݖ_vka !ϫZ!(d[OE[k'ِ [b*tؓf؞4Rmv:4Ψ[1zb>^Bۢ$@/j#%gsʟJVnwެ6.V-x.vkJ:3$kQ/rqT6@$!SeϓN+`{-Bۢ$@/qc^آ}`ˢ%u!3PVv9=:lw),{d,,4@غ~x-[qs&HfQ:DX DjBD;3Q\]R* 0Qs{[ ' Y [E|qsQյE(P`F4O7)8漩X]>@:a7*QL B6N@XZ~n*U=*%|%JZJ~lnfjʖ]2,oT ћ1NBgN|+^;]Gs"?S-X(ZE eh)H30V=m 'ZikT2h찘h=-)9 0mp ED)iVQs5YN*'T3Ve]Ma`@x ? msL]`G|g0uB~NG7zX50\ݖmi~vOW2]*u#}hw5G%zu}i q2Be g\W^h~H ɣ^A]7UhK:i (ѐ,- ~fYB\lw]HœuɊ$\#G!(͵{1b;Vgz:L2=g`DFƥ"L,U#2Dž8C!NݏEӮN(>e D$Pm_( ǂ;žH^n)hC>{= R+[V&Rs'%jع Z,7[ĚrtUq/xћ}]hj"HrQ 1Ӣv;CTADž8C!N݋֚@Y'ԑc#@)ڱr zٗ?aiM*}$t]D(k0?KeK *QyvuBU-'3k3dA̢x84 u tl|?;úz]DSS<_LC <0:S*5OZA Xت-uZU4M=Uvϕ >g?Xk..72<2\|zh5S/篸  Q?@ |@/IY8MH9@8 +!轵2W#*܍5'ZuڌrMJ&[Q7[/՟Hi!BaxhKnz0_&-`g,9'ˆBtBy2p'3 woZZupg$PY-ȧ7aC(H{Fub/*cdnG&Z\Vd1e7;%7,0گ 'vKdڂ4 " H B5' Li}@0춱b8v6`zkJl#klmy/d)yrqQ 'vKdGiQ5v"XVyi` ]%MB~N QFa݊fsz@3!#Ylmy/d)yrqQ 'vKdڠ` >]SkX/՟Hi!Bžo eU%vO u˅|+ +"I` lv> K$qKkro76|ՂYavs#urVƙ@ Ql۸g~?.<; +X ׄ7X) 0Qs{[ vNy&974!f1ېGH"tt'q%@(} Kj2\|o(FZ7G/]9,)/G+5O^PC taRX@$Oy^ gyBCEg鹇PE"}@[ꩪ%M'(d3֗aN $futureValue = CashFlowValidations::validateFutureValue($futureValue); $type = CashFlowValidations::validatePeriodType($type); } catch (Exception $e) { return $e->getMessage(); } // Validate parameters if ($numberOfPeriods < 0) { return ExcelError::NAN(); } return self::calculatePresentValue($rate, $numberOfPeriods, $payment, $futureValue, $type); } /** * NPER. * * Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate. * * @param mixed $rate Interest rate per period * @param mixed $payment Periodic payment (annuity) * @param mixed $presentValue Present Value * @param mixed $futureValue Future Value * @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * * @return float|string Result, or a string containing an error */ public static function periods( $rate, $payment, $presentValue, $futureValue = 0.0, $type = FinancialConstants::PAYMENT_END_OF_PERIOD ) { $rate = Functions::flattenSingleValue($rate); $payment = Functions::flattenSingleValue($payment); $presentValue = Functions::flattenSingleValue($presentValue); $futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue); $type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type); try { $rate = CashFlowValidations::validateRate($rate); $payment = CashFlowValidations::validateFloat($payment); $presentValue = CashFlowValidations::validatePresentValue($presentValue); $futureValue = CashFlowValidations::validateFutureValue($futureValue); $type = CashFlowValidations::validatePeriodType($type); } catch (Exception $e) { return $e->getMessage(); } // Validate parameters if ($payment == 0.0) { return ExcelError::NAN(); } return self::calculatePeriods($rate, $payment, $presentValue, $futureValue, $type); } private static function calculateFutureValue( float $rate, int $numberOfPeriods, float $payment, float $presentValue, int $type ): float { if ($rate !== null && $rate != 0) { return -$presentValue * (1 + $rate) ** $numberOfPeriods - $payment * (1 + $rate * $type) * ((1 + $rate) ** $numberOfPeriods - 1) / $rate; } return -$presentValue - $payment * $numberOfPeriods; } private static function calculatePresentValue( float $rate, int $numberOfPeriods, float $payment, float $futureValue, int $type ): float { if ($rate != 0.0) { return (-$payment * (1 + $rate * $type) * (((1 + $rate) ** $numberOfPeriods - 1) / $rate) - $futureValue) / (1 + $rate) ** $numberOfPeriods; } return -$futureValue - $payment * $numberOfPeriods; } /** * @return float|string */ private static function calculatePeriods( float $rate, float $payment, float $presentValue, float $futureValue, int $type ) { if ($rate != 0.0) { if ($presentValue == 0.0) { return ExcelError::NAN(); } return log(($payment * (1 + $rate * $type) / $rate - $futureValue) / ($presentValue + $payment * (1 + $rate * $type) / $rate)) / log(1 + $rate); } return (-$presentValue - $futureValue) / $payment; } }