Odd behavior with NSUInteger - can't convert to float properly - objective-c

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.

Related

How to use decimal variable

I am using a For loop to cycle through variables in an array that contain percentages. For each value I run through an equation to give me an average of all the percentages. The only problem is that I am unsure how to change the variable types to accommodate decimals whilst also work in with my equation.
// Calculate average of all percentages for specific exercise
long totalNumber = 0;
int temp;
long numberOfObjects = [iterationArray count];
for (NSArray *object in iterationArray) {
temp = [(NSNumber *)[object objectAtIndex:4] intValue]/100;
totalNumber = totalNumber + temp;
}
exercisePercentage = (totalNumber/numberOfObjects)*100;
return exercisePercentage;
I know that temp is the variable that needs to be a decimal. I was considering using an NSDecimalNumber but didn't know how to fit in with the rest of the code to return a long value.
I've tried with making temp a double or float but both return 0 on the line temp = [(NSNumber *)[object objectAtIndex:4] intValue]/100; despite the fact that [(NSNumber *)[object objectAtIndex:4] intValue] is 80.
Division of int with int always returns int, so you need to convert one value into float or double, something like this:
// Calculate average of all percentages for specific exercise
double totalNumber = 0.0;
double temp;
long numberOfObjects = [iterationArray count];
for (NSArray *object in iterationArray) {
temp = [(NSNumber *)[object objectAtIndex:4] intValue]/100.0;
totalNumber = totalNumber + temp;
}
exercisePercentage = (totalNumber/numberOfObjects)*100.0;
return exercisePercentage;
See it's 100.0, now it should work.
Please change the type of temp form int to float or double.
double temp;
float temp;

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

speed up this Standard Deviation method

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

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.

NSNumber and decimal value

I have an NSNumber like this for example = 1978, i would like to convert this for : 1K9, seconde example : 35700 convert to : 35K7 ( where "k" is kilometers and "M" is meters, how i can do this
thanks
int temp;
NSNumber *yourNumber;//the number you enter from some where
NSString *newValue;
if([yourNumber intValue]>1000){
temp = [yourNumber intValue] % 1000 ;//your number module 1000
newValue= [[temp stringValue]stringByAppendingString:#"K"];
}
Note: I haven't my mac with me, if the [temp stringValue] gives any worning&error please inform me.
Here's how:
NSNumber *initialNumber = [NSNumber numberWithInt:35700];
NSString *resultString = [NSString stringWithFormat:#"%iK%i", floor(initialNumber / 1000), floor((initialNumber % 1000) / 100)];
Basically you can work with the internal number data.
Assuming you are working on a meter-based value, you might want something like this:
NSNumber *sourceValue = ... // your NSNumber value from any source
int meters = sourceValue.intValue;
int km = floor(meters / 1000); // only your kilometers
int sub_km = meters % 1000; // only the part behind the kilometers
int first_sub_km = floor(sum_km / 100); // the first digit of the subrange
NSString *readable = [NSString stringWithFormat:#"%iK%i", km, first_sub_km];
First, you split the meters into <= 1000 and > 1000.
Then you'll just have to put that out formatted, with a K in between.
Write your own subclass of NSNumberFormatter. In this subclass you can implement the calculation logic.
The logic might look like this.
Devide the value by thousend and add your "k"
if you want to have the first digit of hundreds get the thired last digit of your value
return the new string