Objective C Maths - objective-c

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);

Related

Using NSDecimalNumber in for Loop?

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

Half Life Formula ~ Objective-C

Nt = N0e-λt
N0 is the initial quantity
Nt is the quantity that still remains after a time t,
t1/2 is the half-life
τ is the mean lifetime
λ is the decay constant
I am pretty stuck on how to make this into a formula for objective-c and I require it.
double sourceStart = [textField.text doubleValue];
double sourceNow = 0;
double daysBetween = 8;
if (textField.text.length > 0) {
//Find how many half lives have been accumulated
double totalNumberOfHalfLives = daysBetween / sourceHalfLife;
//Find the factor
double reductionFactor = pow(0.5, totalNumberOfHalfLives);
//Find the source strength now
double sourceNow = sourceStart * reductionFactor;
}
I'm assuming I need something a long the lines of this? or completely wrong.
Then, I also need to be able to find how many days have passed between a certain period of days, for instance. Start Date = Apr 15th Now Date = Apr 25th, 10 days between.. How do I work that out in objective c? As well as my original question.
This will do it (in straight C, but it'll work as-is in Objective-C, and you can extract the logic easily enough):
#include <stdio.h>
#include <math.h>
int main(void) {
double start_quantity = 100;
double half_life = 8;
double days = 16;
double end_quantity = start_quantity * pow(0.5, days / half_life);
printf("After %.1f days with a half life of %.1f days, %.1f decays to %.1f.\
n",
days, half_life, start_quantity, end_quantity);
return 0;
}
and outputs:
paul#local:~/src$ ./halflife
After 16.0 days with a half life of 8.0 days, 100.0 decays to 25.0.
paul#local:~/src$
For the second part of your question, you can store dates in an NSDate, and use the timeIntervalSinceDate: method to get the time between them in seconds. Something like this:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
const int kSecsInADay = 86400;
NSDate * startDate = [NSDate dateWithTimeIntervalSinceNow:-16 * kSecsInADay];
NSDate * endDate = [NSDate date];
NSTimeInterval seconds_diff = [endDate timeIntervalSinceDate:startDate];
double days_diff = seconds_diff / kSecsInADay;
NSLog(#"There are %.1f days between %# and %#.", days_diff,
[startDate description], [endDate description]);
}
return 0;
}
which outputs:
There are 16.0 days between 2014-04-09 21:41:12 +0000 and 2014-04-25 21:41:12 +0000.
Notes:
[NSDate date] returns an NSDate object representing the current time.
[NSDate dateWithTimeIntervalSinceNow:seconds] returns an NSDate object that's seconds seconds away from the current time. In this case, I've created it exactly 16 days before the current date. Based on the comments, in your case you'll also want to create startDate with [NSDate date], and then store it somewhere so you can calculate the difference between it and the current time at some point in the future.

How would I convert a double value to hh:mm?

As it says above...
I don't need the seconds with that as it does not constantly update.
I have searched around this site and google for a few hours and couldn't find anything exactly like what I need.
Here is my code:
//Sets the percentage calculation
double percent = level / 100;
//Calculates the time left while using the following
double a = 40 * percent;
double b = 400 * percent;
double c = 7 * percent;
double d = 6 * percent;
aTime.text = [NSString stringWithFormat:#"%f", a];
bTime.text = [NSString stringWithFormat:#"%f", b];
cTime.text = [NSString stringWithFormat:#"%f", c];
dTime.text = [NSString stringWithFormat:#"%f", d];
After a calculation of, say, 50% of 7 hours, it currently gives 3.5 hours. I want it to say 3:30.
The calculations, as you can see, are static minus the level calculation, I just need to know how to convert the decimal to hh:mm (maybe even days for the 400 hours one).
Note: all the numbers above (40, 400, 7, 6) are in hours.
Example:
double hours = 7;
double percent = 0.5; // 50 percent
int value = hours * percent * 60; // value in minutes
NSString *formatted = [NSString stringWithFormat:#"%02d:%02d",value/60,value%60];
NSLog(#"%#",formatted);
Output:
03:30

Issue with calculation

Can anyone see if there's problem with the way i handle the calculation below? I seemed to be getting "You scored 0" at runtime even when the answer is actually correct.
- (void)countGain{
int gain = 0;
int percentage;
if ([answer objectForKey:#"1"] == [usrAnswer objectForKey:#"1"]) {
gain += 1;
}
percentage = (gain / 10) * 100;
NSString *scored = [[NSString alloc] initWithFormat:#"You scored %d",percentage];
score.text = scored;
rangenans.text = [answer objectForKey:#"1"];
[scored release];
}
What is the point doing:
percentage = (gain / 10) * 100;
Use
percentage = gain * 10;
Rest looks good. You shouldn't divide integers. What if you get 3/10 and this is int value?
In condition change
if([answer objectForKey:#"1"] == [usrAnswer objectForKey:#"1"])
To:
if([[answer objectForKey:#"1"] isEqualToString:[usrAnswer objectForKey:#"1"]])
This is integer arithmetic. Try:
percentage = gain * 10;
or
percentage = (gain * 10 ) / 100;
or
percentage = ((float)gain / 10) * 100;
Note that in any of the above, you only have 10 options for the "percentage", so percentage = gain * 10; is the simpler.
The problem is that you are trying to compare NSStrings and == compares the assresses of strings. You want to compare their values
e.g.
NSString *correct = #"Yes";
NSString *answer = ..... from some entry;
Then these two NSStrings will point to different bits of memory.
to compre with the user replied you need to compare values using the isEqualToString: method
e.g.
gain += [correct isEqualToString:answer] ? 1 : 0;
In your code == failed each time so gain was always 0. So the int division problem never occureed - but it would have when gain became 1 etc.

Objective-c format time left until certain date

I'm creating a countdown timer and I need to printout the time left (hour:minute:seconds) until a specific date. I've found how to get the time interval between Now and the target date but I don't know how to format the time interval as a string. Does NSDateFormater work on NSTimeInterval?
NSTimeInterval is in seconds, use divide and remainder to break it up and format (code untested):
NSString *timeIntervalToString(NSTimeInterval interval)
{
long work = (long)interval; // convert to long, NSTimeInterval is *some* numeric type
long seconds = work % 60; // remainder is seconds
work /= 60; // total number of mins
long minutes = work % 60; // remainder is minutes
long hours = work / 60 // number of hours
// now format and return - %ld is long decimal, %02ld is zero-padded two digit long decimal
return [NSString stringWithFormat:#"%ld:%02ld:%02ld", hours, minutes, seconds];
}
You would first compare two NSDate objects to retrieve the difference in seconds between the two, the NSDate method you should use is
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
Then you could simply write a function to parse the seconds into hours/minutes/seconds, for example you could use this (untested):
-(NSDictionary*)createTimemapForSeconds:(int)seconds{
int hours = floor(seconds / (60 * 60) );
float minute_divisor = seconds % (60 * 60);
int minutes = floor(minute_divisor / 60);
float seconds_divisor = seconds % 60;
seconds = ceil(seconds_divisor);
NSDictionary * timeMap = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithInt:hours], [NSNumber numberWithInt:minutes], [NSNumber numberWithInt:seconds], nil] forKeys:[NSArray arrayWithObjects:#"h", #"m", #"s", nil]];
return timeMap;
}
This is code from my project:
-(NSString*)timeLeftString
{
long seconds = [self msLeft]/1000;
if( seconds == 0 )
return #"";
if( seconds < 60 )
return [NSString stringWithFormat:
pluralString(seconds,
NSLocalizedString(#"en|%ld second left|%ld seconds left", #"")), seconds];
long minutes = seconds / 60;
seconds -= minutes*60;
if( minutes < 60 )
return [NSString stringWithFormat:
NSLocalizedString(#"%ld:%02ld left",#""),
minutes, seconds];
long hours = minutes/60;
minutes -= hours*60;
return [NSString stringWithFormat:
NSLocalizedString(#"%ld:%02ld:%02ld left",#""),
hours, minutes, seconds];
}
msLeft --- my function that returns time in milliseconds
pluralString --- my function that provides different parts of format string depending on the value (http://translate.sourceforge.net/wiki/l10n/pluralforms)
Function returns different format for different timer values (1 second left, 5 seconds left, 2:34 left, 1:15:14 left).
In any case, progress bad should be visible during long operation
One more thought: In case that time left is "small" (less then a minute?), probably time left should not be shown --- just progress bar left to reduce interface "visual noise".