ios理财类的app中很多涉及到等额本息的计算方式
然而等额本息的计算也是有两种方法的
因为涉及到金额的都是保留小数后两位的运算,但是,往往实际操作过程中的运算不止两位小数
这个时候我们是用NSDecimalNumber进行计算呢,还是用double进行计算呢
直接上代码了
/**
等额本息收益计算
* 公式: 每月本息还款额=(投资金额*月利率*(1+月利率)^还款月数)/(((1+月利率)^还款月数)-1)
@param interest 年化收益
@param investAmount 投资金额
@param month 投资月份
@param isMonth 是否是按月计算
@param addrate 加息额度
@param isAddlixi 是否是加息计算
@return 收益或加息收益
*/
-(double)calculatePrincipalAndInterestBidWithInvestInterest:(double)interest
amount:(NSString *)investAmount AndMonth:(double )month AndStyle:(BOOL)isMonth AndAddRate:(double)addrate andBool:(BOOL)isAddlixi
{
if ([investAmount isEqualToString:@""]) {
investAmount = @"0";
}
NSDecimalNumberHandler *roundBanker = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers
scale:2.0f
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:YES];
NSDecimalNumber *investAmountDec = [[NSDecimalNumber alloc] initWithString:investAmount];//投资金额
NSDecimalNumber *monthInterestDec = [[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",interest/100]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",12.00]]];//月利率
NSDecimalNumber *nomonthInterestDec = [[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",(interest - addrate)/100]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",12.00]]];//未加息月利率
if (!isMonth) {
//按天标,转化为月份
month = month/30.00;
}
NSDecimalNumber *monthDec = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",month]];//还款月数
// * 公式: 每月本息还款额=(投资金额*月利率*(1+月利率)^还款月数)/(((1+月利率)^还款月数)-1)
NSDecimalNumber *decNum1 = [[[[[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%d",1]] decimalNumberByAdding:monthInterestDec] decimalNumberByRaisingToPower:month] decimalNumberByMultiplyingBy:monthInterestDec] decimalNumberByMultiplyingBy:investAmountDec];
NSDecimalNumber *decNum2 = [[[[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%d",1]] decimalNumberByAdding:monthInterestDec] decimalNumberByRaisingToPower:month] decimalNumberBySubtracting:[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%d",1]]];
NSDecimalNumber *monthIncomeDec = [decNum1 decimalNumberByDividingBy:decNum2];//月本息还款额
// 每月利息 = 剩余本金x贷款月利率
// 第一个月
NSDecimalNumber *lixi = [investAmountDec decimalNumberByMultiplyingBy:monthInterestDec];
NSDecimalNumber *noaddLixi = [investAmountDec decimalNumberByMultiplyingBy:nomonthInterestDec];
NSString *benjin = [NSString decimalNumberCalucate:[NSString stringWithFormat:@"%.2f",monthIncomeDec.doubleValue] originValue2:[NSString stringWithFormat:@"%.2f",lixi.doubleValue] calucateWay:2];
// NSDecimalNumber *leftBenjin = [investAmountDec decimalNumberBySubtracting:benjin];
NSString *leftBenjin = [NSString decimalNumberCalucate:[NSString stringWithFormat:@"%.2f",investAmountDec.doubleValue] originValue2:benjin calucateWay:2];
// NSLog(@"利息%@本金%@剩余本金%@",lixi,benjin,leftBenjin);
// NSLog(@"第一个月每月利息%.2f 年化收益 %.2f 每月利率 %@",lixi.doubleValue,interest,monthInterestDec);
// NSLog(@"每个月本息%@",monthIncomeDec);
NSString *allLixi = [NSString stringWithFormat:@"%.2f",lixi.doubleValue];
NSString *addlixi = [NSString decimalNumberCalucate:[NSString stringWithFormat:@"%.2f",lixi.doubleValue] originValue2:[NSString stringWithFormat:@"%.2f",noaddLixi.doubleValue] calucateWay:2];
// NSLog(@"lixica = %@ 第一个第一个利息 = %@ 第二个利息= %@",addlixi,lixi,noaddLixi);
NSLog(@"------------------------");
NSLog(@"本息:%@,本金:%@,利率:%@,利息:%.2f,未加息:%@,加息部分:%@",monthIncomeDec,benjin,monthInterestDec,lixi.doubleValue,noaddLixi,addlixi);
if (month > 1) {
for (int xx = 0 ; xx < month -1; xx ++) {
// 第二个月
double lixi111 = leftBenjin.doubleValue *monthInterestDec.doubleValue;
double lixi222 = leftBenjin.doubleValue *nomonthInterestDec.doubleValue;
// NSString *lixi111 = [NSString decimalNumberCalucate:leftBenjin originValue2:[NSString stringWithFormat:@"%f",monthInterestDec.doubleValue] calucateWay:3];
NSString *benjin111 = [NSString decimalNumberCalucate:[NSString stringWithFormat:@"%.2f",monthIncomeDec.doubleValue] originValue2:[NSString stringWithFormat:@"%.2f",lixi111] calucateWay:2];
NSString *leftBenjin111 = [NSString decimalNumberCalucate:leftBenjin originValue2:benjin111 calucateWay:2];
// NSLog(@"每月利息%.2f ",lixi111.doubleValue);
leftBenjin = leftBenjin111;
double x = lixi111 - lixi222;
NSString *lixica = [NSString decimalNumberCalucate:[NSString stringWithFormat:@"%.2f",lixi111] originValue2:[NSString stringWithFormat:@"%.2f",lixi222] calucateWay:2];
addlixi = [NSString decimalNumberCalucate:addlixi originValue2:lixica calucateWay:1];
// NSLog(@"lixica = %@ 第一个利息 = %.2f 第二个利息= %.2f",lixica,lixi111,lixi222);
// NSLog(@"上次剩余本金%@每月利息%.2f这次本金%@这次剩余本金%@",leftBenjin,lixi111,benjin111,leftBenjin111);
NSLog(@"本息:%@,本金:%@,利率:%@,利息:%.2f,未加息:%.2f,加息部分:%@",monthIncomeDec,benjin111,monthInterestDec,lixi111,lixi222,lixica);
NSLog(@"x== %f********%@",x,addlixi);
if (isAddlixi) {
allLixi = addlixi;
}else{
allLixi = [NSString decimalNumberCalucate:allLixi originValue2:[NSString stringWithFormat:@"%.2f",lixi111] calucateWay:1];
}
}
}
// NSLog(@"alllixi = %@",allLixi);
// NSDecimalNumber *totalIncomeDec = [[monthDec decimalNumberByMultiplyingBy:monthIncomeDec] decimalNumberBySubtracting:investAmountDec withBehavior:roundBanker];//总还款额 - 本金 = 总收益
return [allLixi doubleValue] > 0 ? [allLixi doubleValue] : 0;
// return [totalIncomeDec doubleValue] > 0 ? [totalIncomeDec doubleValue] : 0;
}
NSDecimalNumber计算方法
+ (NSString *)decimalNumberCalucate:(NSString *)originValue1 originValue2:(NSString *)originValue2 calucateWay:(NSInteger)calucateWay
{
NSDecimalNumberHandler *numUp = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES];
NSDecimalNumber *decimalNumber1 = [NSDecimalNumber decimalNumberWithString:originValue1];
NSDecimalNumber *decimalNumber2 = [NSDecimalNumber decimalNumberWithString:originValue2];
NSDecimalNumber *product;
switch (calucateWay) {
case 1://+
product = [decimalNumber1 decimalNumberByAdding:decimalNumber2 withBehavior:numUp];
break;
case 2://-
product = [decimalNumber1 decimalNumberBySubtracting:decimalNumber2 withBehavior:numUp];
break;
case 3://*
product = [decimalNumber1 decimalNumberByMultiplyingBy:decimalNumber2 withBehavior:numUp];
break;
case 4:// /
product = [decimalNumber1 decimalNumberByDividingBy:decimalNumber2 withBehavior:numUp];
break;
default:
break;
}
return [product stringValue];
}
因为要计算每个月的本息,所以,在得到每月本息之后所有涉及到本息的计算过程中,都是需要使用两位小数进行,从而得出每月的剩余本金进行接下来的计算
很多理财产品涉及到的加息情况上面也有运算,加息部分不能用加息后的总利息和加息钱的总利息差进行计算,因为在运算过程中,剩余本金是不同的,所以计算每月加息差额之后进行总加息计算