I have a loop i am trying to run with NSDecimalNumber values but the value returned is always the same. I understand NSDecimalNumber isn't mutable but i originally used double values and was getting the wrong result at the end which I assume is some floating point error/rounding error. Here is the code:
double balanceAmount = loanAmountValue;
double rtemp = r / (n * 12);
double intA = balanceAmount * rtemp;
double principalA = payfinal - intA;
double principal = balanceAmount - principalA;
NSDecimalNumber *balDeciminal = (NSDecimalNumber *) [NSDecimalNumber numberWithDouble:balanceAmount];
NSDecimalNumber *rTempDecimal = (NSDecimalNumber *) [NSDecimalNumber numberWithDouble:rtemp];
NSDecimalNumber *payFinalDecimal = (NSDecimalNumber *) [NSDecimalNumber numberWithDouble:payfinal];
NSDecimalNumber *principalDecimal = (NSDecimalNumber *) [NSDecimalNumber numberWithDouble:principalA];
for (n = n * 12; n != 0; --n) {
NSDecimalNumber *realBalanceDecimal = [balDeciminal decimalNumberBySubtracting:principalDecimal];
NSDecimalNumber *interestDecimal = [balDeciminal decimalNumberByMultiplyingBy:rTempDecimal];
NSDecimalNumber *principalDecimalAmount = [payFinalDecimal decimalNumberBySubtracting:interestDecimal];
NSString *tempInterest = [NSString stringWithFormat:#"$%#", interestDecimal];
[interestLabels addObject:tempInterest];
NSString *tempPrincipal = [NSString stringWithFormat:#"$%#", principalDecimalAmount];
[pricipalLabels addObject:tempPrincipal];
NSString *tempBalance = [NSString stringWithFormat:#"$%#", balDeciminal];
[balanceLabels addObject: tempBalance];
}
NSLog(#"%#", balanceLabels);
NSLog(#"%#", pricipalLabels);
NSLog(#"%#", interestLabels);
If NSDecimalNumber doesn't allow me to make these sort of calculations could someone suggest something else that will return a result that is accurate?
Thanks!
EDIT : Double Code
double r = interestAmountValue/200;
//NSLog(#"%f", r);
double n = yearAmountValue;
double rPower = pow(1+r, 0.166666666);
double tophalf = rPower - 1;
double nPower = (-12 * n);
double bothalf = pow(rPower, nPower);
double bothalffinal = 1 - bothalf;
double tempfinal = tophalf / bothalffinal;
double payfinal = loanAmountValue * tempfinal;
double totalPaymentd = payfinal * n * 12;
double totalInterestd = totalPaymentd - loanAmountValue;
for (n = n * 12; n != 0; --n) {
double realBalance = balanceAmount - principalA;
double interest = balanceAmount * rtemp;
NSLog(#"%f", interest);
double principalAmount = payfinal - interest;
balanceAmount -= principalA;
}
Hi the problem you were having is that you weren't checking was the loan payed off and you were entering negative numbers meaning the underlying problem is with the spreading of payments.
double loanAmountValue = 100000;
double balanceAmount = loanAmountValue;
double n = 30;
double interestAmountValue = 8;
double r = interestAmountValue/1200;
double rtemp = r/(n*12);
double intA = balanceAmount * rtemp;
//NSLog(#"%f", r);
double rPower = pow(1+r, 0.166666666);
double tophalf = rPower - 1;
double nPower = (-12 * n);
double bothalf = pow(rPower, nPower);
double bothalffinal = 1 - bothalf;
double tempfinal = tophalf / bothalffinal;
double payfinal = loanAmountValue * tempfinal;
double principalA = balanceAmount - intA;
double totalPaymentd = payfinal * n * 12;
double totalInterestd = totalPaymentd - loanAmountValue;
for (n = n * 12; n != 0; --n) {
double realBalance = balanceAmount - principalA;
double interest = balanceAmount * rtemp;
NSLog(#"interest: %f", interest);
NSLog(#"rtemp: %f",rtemp);
double principalAmount = payfinal - interest;
// Check for negative balance
if (balanceAmount < principalAmount) {
NSLog(#"Balance Amount: %f",balanceAmount);
NSLog(#"Months Left: %f",n);
break;
}
balanceAmount -= principalAmount;
NSLog(#"balanceAmount %f",balanceAmount);
}
Using your code with the values of n = 30 years, loanAmountValue = 100000, and interestAmountValue = 8%. I had the loan payed off with 63 months left. I assume r = interestAmountValue/1200 instead of 200 to get percentage per month?
Regarding use of NSDecimal number I don't know what impact floating point precision will have on your corrected mortgage calculator, but the problem you were having was not with using double data types it is with the spreading of payments.
I wonder what makes you think that putting a double into an NSDecimalNumber could somehow create extra precision. And it looks to me that in the loop you are always doing the exact same calculation.
double gives about 15 to 16 decimals of precisions. If you are calculating a loan for 30 years, it is very unlikely that you will run into problems due to not having enough precision. I'd suggest that you post your code with double precision numbers and let people have a look at where you went wrong.
The code needs to be cleaned and checked:
The for loop is not producing a change per iteration.
Use the debugger to figure out why. Perhaps the fact that five variables are not being used is a hint.
The following variables are not used:
intA
principalA
principal
principalDecimal
realBalanceDecimal
Related
I am currently working on iOS project, where i use motion data.
I get a good results with pitch and roll values, but yaw value is constantly drifting. I have applied Kalman filter and results are remain the same.
Does anyone has an idea how to solve it?
Here is some source code (Objective C)
[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryCorrectedZVertical
toQueue:[NSOperationQueue currentQueue]
withHandler:^(CMDeviceMotion *motion, NSError *error)
{
//NSString *yaw = [NSString
//stringWithFormat:#" %.3f", motion.attitude.yaw];
NSString *pitch = [NSString
stringWithFormat:#" %.3f", motion.attitude.pitch];
NSString *roll = [NSString
stringWithFormat:#" %.3f", motion.attitude.roll];
//Converting NSSring type variable in to a double
//double a_yaw = [yaw doubleValue];
double a_pitch = [pitch doubleValue];
double a_roll = [roll doubleValue];
CMQuaternion quat = self.motionManager.deviceMotion.attitude.quaternion;
double yaw = 180/M_PI * (asin(2*quat.x*quat.y + 2*quat.w*quat.z));
// Kalman filtering
static float q = 0.1; // process noise
static float r = 0.1; // sensor noise
static float p = 0.1; // estimated error
static float k = 0.5; // kalman filter gain
float x = motionLastYaw;
p = p + q;
k = p / (p + r);
x = x + k*(yaw - x);
p = (1 - k)*p;
motionLastYaw = x;
//Converting angles to degrees
//yaw = yaw * 180/M_PI;
a_pitch = a_pitch * 180/M_PI;
a_roll = a_roll * 180/M_PI;
"yaw" value need a reference to additional coordinate system(camera...).
I have this method to calculate the standard deviation of an array of NSNumber integers, given a mean. The calculation uses NSDecimals to retain the highest resolution. This is currently demanding many cpu cycles, any help to speed it up while retaining the resolution required is appreciated! Thank you.
-(NSDecimal)standardDeviationOf:(NSMutableArray *)array withMean:(NSDecimal)mean {
if (![array count]) return CPTDecimalFromInt(0);
NSDecimal sumOfSquaredDifferences = CPTDecimalFromInt(0);
for (NSNumber *number in array) {
NSDecimal valueOfNumber = CPTDecimalFromInt([number intValue]);
NSDecimal difference = CPTDecimalSubtract(valueOfNumber, mean);
sumOfSquaredDifferences = CPTDecimalAdd(sumOfSquaredDifferences, CPTDecimalMultiply(difference, difference));
}
return CPTDecimalFromDouble(
sqrt(
CPTDecimalDoubleValue(sumOfSquaredDifferences) / [[NSNumber numberWithInt:[array count]] doubleValue]
)
);
}
An NSDecimal has 38 digits of precision, whereas double has roughly 16 digits of precision. But at the end of your loop, when you convert sumOfSquaredDifferences to double for the sqrt function, all the extra precision you had in the NSDecimal is "lost". You might as well perform the arithmetic of your inner loop using double, which should be much faster than NSDecimal:
double sumOfSquaredDifferences = 0;
double valueOfMean = [mean doubleValue];
for (NSNumber *number in array) {
double valueOfNumber = [number intValue];
double difference = valueOfNumber - valueOfMean;
sumOfSquaredDifferences += difference * difference;
}
return CPTDecimalFromDouble(sqrt(sumOfSquaredDifferences /
double([array count])));
How would I go about calculating a compound interest rate, so far I have:
double principal = [[principalLabel text] doubleValue];
NSLog(#"Principal: %lf",principal);
double years = [[yearsLabel text] doubleValue];
NSLog(#"Years: %lf",years);
double months = [[monthsLabel text] doubleValue] / 12;
NSLog(#"Months: %lf",months);
double days = ([[daysLabel text] doubleValue] / 365) / 10;
NSLog(#"Days :%lf",days);
double rate = ([[rateLabel text] doubleValue] / 100);
NSLog(#"Rate: %lf",rate);
double time = years + days + months;
NSLog(#"Time: %lf",time);
double total = pow(principal * (1 - rate), time);
NSLog(#"Total: %lf",total);
double interest = pow(principal * (1 - rate), time) - principal;
NSLog(#"Interest: %lf",interest);
NSString *interestString = [[NSString alloc] initWithFormat:#"%lf",interest];
NSString *totalString = [[NSString alloc] initWithFormat:#"%lf",total];
[interestLabel setText:interestString];
[totalLabel setText:totalString];
So as you can see I have 5 UITextFields for the: principal, rate, years, months, days. At the moment I keep getting some answer that is no where near the actual answer I am after even though my math seems correct I have reviewed my code thoroughly and found no solution.
My desired result is: E.g.
M = P * (1+R)^Y
M = 1000 * (1+0.10)^2
M = 1210
If you place the output from the NSLog messages in your question also, it will be even more helpful to answer your question. Right now an obvious mistake is mentioned below:
In this line of code
double total = pow(principal * (1 - rate), time);
you have 1 - rate, while you need to have
double total = pow(principal * (1 + rate), time);
i am currently trying to do the volume of a sphere but when i run my program it gives me the wrong answer. here is my code:
-(IBAction)calculate
{
double radiusNum = [radius.text doubleValue];
double ansNum = 4/3 * 3.14159 * (radiusNum * radiusNum * radiusNum);
NSString *ans = [NSString stringWithFormat:#"%1.4f Units^3", ansNum];
answer.text = ans;
}
could you please tell me how to fix it an d what i did wrong.
p.s i am using Xcode 4 and thank you in advance
4/3 will be an integer operation.
Actually this is logical mistake.
The method should be as follows:
-(IBAction)calculate
{
double radiusNum = [radius.text doubleValue];
double ansNum = (4 * 3.14159 * (radiusNum * radiusNum * radiusNum))/3;
NSString *ans = [NSString stringWithFormat:#"%1.4f Units^3", ansNum];
answer.text = ans;
}
The order of computing was wrong.
double radiusNum = [radius.text doubleValue];
double ansNum = (pow(radiusNum, 3)*4/3)*3.1415927;
NSString *ans = [NSString stringWithFormat:#"%1.4f Units^3", ansNum];
NSLog(ans);
Here is my situation. Its driving me nuts:
I have an NSMutableArray with a count value of 517. I have a double value that is my multiplier.
double multiplier = 0.1223;
double result = [myArray count] * multiplier; // 63 even (wrong!)
In fact it should be 63.2291. If I go:
double result = [myArray count] * 0.1223; // 63.2291 (right!)
or..
double result = 517 * multiplier; // 63.2291 (right!)
Does this make any sense to anyone?
Addendum:
here is my actual function:
- (double) getValueForPercentage:(double)percVal
{
int adjustedCount = [originalData count] - 1;
double final = percVal * (double)adjustedCount;
return final;
}
I never get any digits beyond the decimal point when I do this. It does however work if I get rid of the "-1", a-la:
- (double) getValueForPercentage:(double)percVal
{
int adjustedCount = [originalData count];
double final = percVal * (double)adjustedCount;
return final;
}
Of course, I need to have the -1.
Second addendum:
Another interesting thing I noted was, if I pass a hard-coded number to this function it works fine, but if I pass the double value that I need to use, it fails:
int pointCount = [srcData getDayCount];
for (int i = 0; i < pointCount; i++) {
double progress = (double)i/(double)(pointCount - 1);
double satv = [srcData getValueForPercentage:progress];
// satv is always a number without any digits beyond the decimal
}
Well, when I started to have these issues i looked around a bit and found no reason or explanation.
What I do now is make everything become an NSNumber and then call doubleValue on it. This should yield the results you're looking for:
NSNumber * pointCount = [NSNumber numberWithUnsignedInt: [srcData getDayCount]];
for (NSInteger i = 0; i < [pointCount intValue]; i++) {
NSNumber * count = [ NSNumber numberWithInt: i ];
double progress = [count doubleValue]/[pointCount doubleValue] - 1.0;
double satv = [srcData getValueForPercentage:progress];
// satv is always a number without any digits beyond the decimal
}
Hope it helps.