trouble with calculating - objective-c

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

Related

Round double in Objective-C

I want to round a double to one decimal place in Objective-C.
In Swift I can do it with an extension:
public extension Double {
/// Rounds the double to decimal places value
func rounded(toPlaces places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
However, apparently you cannot call extensions on primitives from Objective-C so I can't use the extension.
I would be happy to do the rounding either on the double directly or as a string, however, neither of the following is working:
double mydub = 122.12022222223322;
NSString *axtstr = [NSString stringWithFormat:#"%2f", mydub]; //gives 122.120222
double rounded = (round(mydub*10)) / 10.0; //gives 122.100000
How do I convert 122.12022222223322; into 122.1?
You need to put a decimal between the % and 2f
[NSString stringWithFormat:#"%.2f", mydub];
double mydouble = 122.12022222223322;
NSString *str = [NSString stringWithFormat:#"%.2f", mydouble];
// = #"122.12"
.. will not round mydouble. Instead it will only apply format to the output as string.
double d = 122.49062222223322;
NSString *dStr = [NSString stringWithFormat:#"%.f %.1f %.2f %.3f", d, d, d, d];
// = #"122 122.5 122.49 122.491"
As Objective-C shares the language rules from C you can round safely with
#include <math.h>
double rounded = round(mydouble);
// = 122.000000
of course you can shift comma with multiplication and dividing the power of ten you want.
double commashifted = round(mydouble*100.0)/100.0;
// = 122.120000;
If you are really into Objective-C Classes to do same in deluxe have a look into 'NSDecimal.h' in the Foundation Framework.
Last but not least you can do the same with C as you did with swift.
double roundbycomma(int commata, double zahl) {
double divisor = pow(10.0, commata);
return round(zahl * divisor) / divisor;
}

Yaw(angle) value are not stable, it is drifting a few degrees. Does anyone know how to solve it?

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

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

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

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.

Make a float only show two decimal places

I have the value 25.00 in a float, but when I print it on screen it is 25.0000000.
How can I display the value with only two decimal places?
It is not a matter of how the number is stored, it is a matter of how you are displaying it. When converting it to a string you must round to the desired precision, which in your case is two decimal places.
E.g.:
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f", myFloat];
%.02f tells the formatter that you will be formatting a float (%f) and, that should be rounded to two places, and should be padded with 0s.
E.g.:
%f = 25.000000
%.f = 25
%.02f = 25.00
Here are few corrections-
//for 3145.559706
Swift 3
let num: CGFloat = 3145.559706
print(String(format: "%f", num)) = 3145.559706
print(String(format: "%.f", num)) = 3145
print(String(format: "%.1f", num)) = 3145.6
print(String(format: "%.2f", num)) = 3145.56
print(String(format: "%.02f", num)) = 3145.56 // which is equal to #"%.2f"
print(String(format: "%.3f", num)) = 3145.560
print(String(format: "%.03f", num)) = 3145.560 // which is equal to #"%.3f"
Obj-C
#"%f" = 3145.559706
#"%.f" = 3146
#"%.1f" = 3145.6
#"%.2f" = 3145.56
#"%.02f" = 3145.56 // which is equal to #"%.2f"
#"%.3f" = 3145.560
#"%.03f" = 3145.560 // which is equal to #"%.3f"
and so on...
You can also try using NSNumberFormatter:
NSNumberFormatter* nf = [[[NSNumberFormatter alloc] init] autorelease];
nf.positiveFormat = #"0.##";
NSString* s = [nf stringFromNumber: [NSNumber numberWithFloat: myFloat]];
You may need to also set the negative format, but I think it's smart enough to figure it out.
I made a swift extension based on above answers
extension Float {
func round(decimalPlace:Int)->Float{
let format = NSString(format: "%%.%if", decimalPlace)
let string = NSString(format: format, self)
return Float(atof(string.UTF8String))
}
}
usage:
let floatOne:Float = 3.1415926
let floatTwo:Float = 3.1425934
print(floatOne.round(2) == floatTwo.round(2))
// should be true
In Swift Language, if you want to show you need to use it in this way. To assign double value in UITextView, for example:
let result = 23.954893
resultTextView.text = NSString(format:"%.2f", result)
If you want to show in LOG like as objective-c does using NSLog(), then in Swift Language you can do this way:
println(NSString(format:"%.2f", result))
IN objective-c, if you are dealing with regular char arrays (instead of pointers to NSString) you could also use:
printf("%.02f", your_float_var);
OTOH, if what you want is to store that value on a char array you could use:
sprintf(your_char_ptr, "%.02f", your_float_var);
The problem with all the answers is that multiplying and then dividing results in precision issues because you used division. I learned this long ago from programming on a PDP8.
The way to resolve this is:
return roundf(number * 100) * .01;
Thus 15.6578 returns just 15.66 and not 15.6578999 or something unintended like that.
What level of precision you want is up to you. Just don't divide the product, multiply it by the decimal equivalent.
No funny String conversion required.
in objective -c is u want to display float value in 2 decimal number then pass argument indicating how many decimal points u want to display
e.g 0.02f will print 25.00
0.002f will print 25.000
Here's some methods to format dynamically according to a precision:
+ (NSNumber *)numberFromString:(NSString *)string
{
if (string.length) {
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
return [f numberFromString:string];
} else {
return nil;
}
}
+ (NSString *)stringByFormattingString:(NSString *)string toPrecision:(NSInteger)precision
{
NSNumber *numberValue = [self numberFromString:string];
if (numberValue) {
NSString *formatString = [NSString stringWithFormat:#"%%.%ldf", (long)precision];
return [NSString stringWithFormat:formatString, numberValue.floatValue];
} else {
/* return original string */
return string;
}
}
e.g.
[TSPAppDelegate stringByFormattingString:#"2.346324" toPrecision:4];
=> 2.3453
[TSPAppDelegate stringByFormattingString:#"2.346324" toPrecision:0];
=> 2
[TSPAppDelegate stringByFormattingString:#"2.346324" toPrecision:2];
=> 2.35 (round up)
Another method for Swift (without using NSString):
let percentage = 33.3333
let text = String.localizedStringWithFormat("%.02f %#", percentage, "%")
P.S. this solution is not working with CGFloat type only tested with Float & Double
Use NSNumberFormatter with maximumFractionDigits as below:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 2;
NSLog(#"%#", [formatter stringFromNumber:[NSNumber numberWithFloat:12.345]]);
And you will get 12.35
If you need to float value as well:
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f", myFloat];
float floatTwoDecimalDigits = atof([formattedNumber UTF8String]);
lblMeter.text=[NSString stringWithFormat:#"%.02f",[[dic objectForKey:#"distance"] floatValue]];