I am making a grading App for my students, but my comparison operators are not functioning they way I expect them to. My code is as follows;
float FINAL = ((_gradeyouwant - (_quarter1 * 0.2f) - (_quarter2 * 0.2f) - (_quarter3 * 0.2f) - (_quarter4 * 0.2f) - (_quarterM * 0.1f)) / 0.1f);
NSLog(#"q1 = %.2f", _quarter1);
NSLog(#"q2 = %.2f", _quarter2);
NSLog(#"q3 = %.2f", _quarter3);
NSLog(#"q4 = %.2f", _quarter4);
NSLog(#"qM = %.2f", _quarterM);
NSLog(#"qF = %.2f", FINAL);
NSLog(#"grade = %.2f", _gradeyouwant);
if ((FINAL > 4.3f))
{
[_result setText:[NSString stringWithFormat:#"It is not possible to get your desired grade."]];
}else if ((FINAL > 4.0f))
{
[_result setText:[NSString stringWithFormat:#"You would need to get an A+"]];
}else if ((FINAL > 3.7f))
{
[_result setText:[NSString stringWithFormat:#"You would need to get an A"]];
}else if ((FINAL > 3.3f))
ETC. ETC.
When you look at the output with NSLog, it tells me the correct value of everything. However, if I make it so the FINAL is 4.0, it does not print the correct string. I was figuring that when it got to the FINAL > 4.0, it would not run that line. But it does. What am I doing wrong? Thanks so much in advance!
This is pretty much how floats work. Google it, e.g. http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
The system may not be able to precisely store 4.0. It's more a limitation of your CPU and choice of data types. Using a range may very well work.
I'd use an int and emulate the decimal digits, e.g. GPA * 100.
Related
I worked a lot in it and can't find a solution. Even the title can't explain clearly.
I have three values weight, quantity and total
I had done the following
float wq = [[weightarray objectAtIndex:selectedint]floatValue];
float q = [quantity floatValue];
float total = wq * q;
for ex, if
[weightarray objectAtIndex:selectedint] = #"3.14";
quantity = 4;
then the result is
wq = 3.140000 q= 4.000000 total = 12.560000
but I need
wq = 3.14 total = 12.56
what to do?
I searched a lot, someone suggests to use NSDecimal,
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
but the scale is not 2 here, wq value may have 3 or four numbers after point.
If the total = 2.30000100 means I need total = 2.300001
how to solve this?
I'm not entirely sure what it is your asking for, but it seems as if you want the values to only display a 2 d.p. In which case you could use a string format like so:
NSString *output = [NSString stringWithFormat:#"float = %.2f", 3.14];
The .2 specifies that the float should be justified to 2 d.p.
Hope this helps
There may be a more direct way to achieve it (which I don't know) but here's a suggestion...
Convert to string as you already do.
Use [myString hasSuffix:#"0"] to see if it ends in zero.
Use [myString substringToindex:[myString length]-1] to create a new string without the final zero.
Repeat.
I know it's not elegant, but unless someone has a better solution, this will at least do what you want.
UPDATE: scratch that - I just discovered [myString stringByTrimmingCharactersInSet:set]. Surely this must be what you need...?
Finally solution found, thanks to Martin
float total = 12.56000;
NSString *s = [NSString stringWithFormat:#"%f", total];
NSLog(#"%#",s);
BOOL success;
success =NO;
while(!success)
{
if ([s hasSuffix:#"0"])
{
s = [s substringWithRange:NSMakeRange(0,[s length]-1)];
}
else if ([s hasSuffix:#"."])
{
s = [s substringWithRange:NSMakeRange(0,[s length]-1)];
success = YES;
}
else
success = YES;
}
NSLog(#"%#",s);
if total = 12.560000 it returns total = 12.56
if total = 12.000000 it returns total = 12
if total = 10.000000 it returns total = 10
if total = 12.3000100 it returns total = 12.30001
I know this isn't going to be a challenging exercise, but I thought I'd ask, just in case there's some methods already in objective-c etc.
In my app I only handle a 2 number version number e.g. 1.5
I want to upgrade this to 4 numbers which could have up to 4 digits.
So I need to handle existing numbers and return true of false when passed database version and the bundle version numbers.
At the moment I simply do
NSString *strOnePointFive = #"1.5";
if (dblDBVersion < [strOnePointFive doubleValue]) {
}
This is a duplicate, was in other formats. Here are some answers to how to handle the version numbers, either equal, greater or below the required version number. Which is answer in this link..
NSString *reqSysVer = #"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
isSupported = YES;
else
isSupported = NO;
What I do is take that string and break it into components:
NSArray *array = [myVersion componentsSeparatedByCharactersInSet:#"."];
NSInteger value = 0;
NSInteger multiplier = 1000000;
for(NSString *n in array) {
value += [n integerValue] * multiplier;
multiplier /= 100;
}
What this does is give you a normalized value you can use for comparison, and will generally compare releases that have different "depths", ie 1.5 and 1.5.2.
It breaks if you have more than 100 point releases (ie any number is > 100) and also will declare 1.5.0 == 1.5. That said, its short, sweet, and simple to use.
EDIT: if you use the NSString 'compare:options:' method, make sure you have your string well groomed:
s1 = #"1.";
s2 = #"1";
NSLog(#"Compare %# to %# result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
s1 = #"20.20.0";
s2 = #"20.20";
NSLog(#"Compare %# to %# result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
2012-09-06 11:26:24.793 xxx[59804:f803] Compare 1. to 1 result 1
2012-09-06 11:26:24.794 xxx[59804:f803] Compare 20.20.0 to 20.20 result 1
Okay so I'm trying to get my values rounded up to the nearest whole number with an IBAction.
So 1.88 -> 2.00 ,
11.40 -> 12.00 ,
111.01 -> 112.00, etc.
-
-(IBAction)roundUp:(id)sender
{
float floatRoundValue=lblTotalRound.text floatValue];
ceilf(floatRoundValue);
NSString *stringRoundValue = [NSString stringWithFormat:#"%1.0f", floatRoundValue];
lblTotalRound.text=stringRoundValue;
}
That's what I got. But it's still rounding down below .5 and to the nearest integer
(Ex. 1.19 -> 1 , i need 1.19 -> 2.00).
I've tried %1.2f but the value doesnt change at all.
What am I doing wrong?
ceilf doesn't modify the value you pass in. It returns a modified value.
floatRoundValue = ceilf(floatRoundValue);
ceilf is a function that returns a value (https://developer.apple.com/library/mac/#documentation/Darwin/Reference/Manpages/man3/ceil.3.html) , you simply need to change that line to the following.
floatRoundValue = ceilf(floatRoundValue);
So the complete code would in your case it would be something like this.
-(IBAction)roundUp:(id)sender
{
float floatRoundValue=lblTotalRound.text floatValue];
floatRoundValue = ceilf(floatRoundValue);
NSString *stringRoundValue = [NSString stringWithFormat:#"%1.0f", floatRoundValue];
lblTotalRound.text=stringRoundValue;
}
If you need to have a $ sign before :
-(IBAction)roundUp:(id)sender
{
float floatRoundValue=(lblTotalRound.text floatValue];
floatRoundValue = ceilf(floatRoundValue);
NSString *stringRoundValue = [NSString stringWithFormat:#"$%1.0f", floatRoundValue];
lblTotalRound.text=stringRoundValue;
}
NSString Class Reference
Hey I am trying to calculate monthly repayments based on loan amount, interest rate and number of years.
I have come up with the following, however there seems to be a difference between my calculations and other loan calculators on the internet. my test data was $1000 loan amount, 5% interest over a period of 1 year. this gives me a monthly payment of 85.61 and a total payment as 1027.29
Here is the code that calculates this.
double LoanAmount = la; //loan amount
double InterestRate = ir; //interest rate
double NumberOfYears = noy; //number of years
double interestRateDecimal = InterestRate / (12 * 100);
double months = NumberOfYears * 12;
double rPower = pow(1+interestRateDecimal,months);
monthlyPayments = LoanAmount * interestRateDecimal * rPower / (rPower - 1);
totalPayments = monthlyPayments * months;
yearlyPayments = monthlyPayments * 12;
totalInterest = totalPayments - LoanAmount;
Is the formula I am using correct or are there errors?
Any help would be appreciated.
Thank you very much
I was a little bit bored so I put the monthly rate formula I got from the internet into code that uses NSDecimalNumber.
As you will see it's a big pita to use NSDecimalNumbers. But you are writing financial software, and your customers expect results that are correct.
And once again, I'm pointing you at Marcus Zarras article DON’T BE LAZY WITH NSDECIMALNUMBER (LIKE ME).
enjoy.
NSDecimalNumber *loan = [NSDecimalNumber decimalNumberWithString:#"25000"];
NSDecimalNumber *annualInterestRate = [NSDecimalNumber decimalNumberWithString:#"6"]; // 6%
annualInterestRate = [annualInterestRate decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:#"100"]]; // 0.06 i.e. 6%
NSInteger numberOfPayments = 36;
// (loan * (interest / 12)) / (1 - (1 + interest / 12) ^ -number)
// ^^^^^^^^^^^^^ temp1
// ^^^^^^^^^^^^^^^^^^^^^^^^ temp2
// ^^^^^^^^^^^^^ temp1
// ^^^^^^^^^^^^^^^^^^^ temp4
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temp5
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temp6
NSDecimalNumber *temp1 = [annualInterestRate decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:#"12"]];
NSDecimalNumber *temp2 = [temp1 decimalNumberByMultiplyingBy:loan];
NSDecimalNumber *temp4 = [[NSDecimalNumber one] decimalNumberByAdding:temp1];
NSDecimalNumber *temp5 = [[NSDecimalNumber one] decimalNumberByDividingBy:[temp4 decimalNumberByRaisingToPower:numberOfPayments]];
NSDecimalNumber *temp6 = [[NSDecimalNumber one] decimalNumberBySubtracting:temp5];
NSDecimalNumber *monthlyRate = [temp2 decimalNumberByDividingBy:temp6];
NSLog(#"Monthly rate: %#", monthlyRate);
hope it's correct though. I usually don't have to deal with NSDecimalNumbers.
This is how you should calculate your monthly payment.
NSDecimalNumber monthlyPayment = LoanAmount * interestRateDecimal / (1 - (pow(1/(1 + interestRateDecimal), months)));
I suggest using NSDecimalNumbers too.
In my application I have a music player, which plays music with a length of 0:30 seconds.
However in a UILabel I am currently displaying the progress, and as it is a float, the label is displaying i.e 14.765.
I would appreciate it if you could tell me how I could get the label to display
0:14 rather than 14.765.
Also, I would appreciate it if you could tell me how I could display 0:04 if the progress was 4seconds in.
This works properly:
float time = 14.765;
int mins = time/60;
int secs = time-(mins*60);
NSString * display = [NSString stringWithFormat:#"%d:%02d",mins,secs];
Results:
14.765 => 0:14
30.000 => 0:30
59.765 => 0:59
105.999 => 1:45
EDIT
In addition the 'one liner':
float time = 14.765;
NSString * display = [NSString stringWithFormat:#"%d:%02d",(int)time/60,(int)time%60];
You first need to convert your float to an integer, rounding as you wish. You can then use the integer division, /, and remainder, % operations to extract minutes and seconds and produce a string:
float elapsedTime = 14.765;
int wholeSeconds = round(elapsedTime); // or ceil (round up) or floor (round down/truncate)
NSString *time = [NSString stringWithFormat:#"%02d:%02d", wholeSeconds/60, wholeSeconds%60];
The %02d is the format specification for a 2-digits, zero padded, integer - look up printf in the docs for full details.
//%60 remove the minutes and int removes the floatingpoints
int seconds = (int)(14.765)%60;
// calc minutes
int minutes = (int)(14.765/60);
// validate if seconds have 2 digits
NSString time = [NSString stringWithFormat:#"%i:%02i",minutes,seconds];
that should work. Can't test it i'm on Win currently