Convert float representing hours to integer hours and minutes - objective-c

I'm using the standard equation of distance / speed = arrival time. This works fine, but the answer is a float number and most people would find it awkward to convert something like 1.75 hrs to be 1 hr and 45 minutes.
I want to take that final float number result and extract the hour(s) separately from the minutes as integers.
Here is what I've tried:
-(IBAction)calculate:(id)sender {
float spd=[speed.text floatValue];
float dist=[distKnots.text floatValue];
//this give me the answer as a float
float arr=(dist/bs);
//this is how I showed it as an answer
//Here I need to convert "arr" and extract the hours & minutes as whole integers
arrivalTime.text=[NSString stringWithFormat:#"%0.02f", arr];
[speed resignFirstResponder];
}
And this is the conversion I tried to do -- and on paper it works, but in code it's full of errors:
int justHours = arr*60;
int justMinutes = (arr*60)-(justHours*60);
//then for the user friendly answer:
arrivalTime.text=[NSString stringWithFormat:#"%n hours and %n minutes", justHours, justMinutes];
I'm new to Objective-C and hoping there is a way to get this to work or a better way altogether to resolve this.

Your arr variable is already measured in hours, so you shouldn't be scaling it, just rounding it down:
int justHours = (int)arr;
and then your minutes is sixty times the (integer) difference between the original and rounded hours (i.e. the fractional part).
int justMinutes = (int)((arr - justHours) * 60);

The int justHours = arr/60; seems to be incorrect, it should be int justHours = arr;.

check the NSNumber numberFormater class. I believe you can wrap your float with time format and the return it to the user.

Related

How to combine 2 different integers to create a single float (or a double)

I'm Cesare from Italy (please excuse my english), this is my first question posted on StackOverflow and I'm pretty new to Objective-C... I hope I won't make a mess on my first try.
I would like to "combine" two integers that I already have to create a new float (or a double).
By "combine", I mean that I'd like to have the first int before the point and the second int after the point, I'm not trying to convert from int to float. Maybe an example could explain better what I'm trying to do:
First int: 7
Second int: 92
The float I'm trying to get: 7.92
I looked for a previous question like mine but I haven't found anything, maybe because what I'm trying to do is pretty dumb (I have a UIPickerView with 2 components, each containing hundreds of integers, and I'm trying to create a float or double variable that has the selection of the first component before the point and the selection of the second component after the point).
Thanks in advance for your help,
Cesare
Just think about what the definition and/or the purpose of the decimal point is. It separates the part of the number which is less than one from the part greater than or equal to one.
So, keep dividing the part after the decimal point until it's less than 1:
int firstPart = 7;
int secondPart = 92; // or whatever
float f = secondPart;
while (f >= 1) {
f /= 10;
}
f += firstPart;
I know this is later, but came across a similar situation. Maybe this is more efficient.
Take the second number, 92 and divide it by 100. That gives you .92. Add that to the first number. That can give you 7.92. However, since you're adding integers that you want converted to a float, you'll need to cast the numbers when adding them. Like this:
int firstPart = 7;
int secondPart = 92;
float afterDecimalPlace = (float)secondPart/100.0;
float numberAsFloat = (float)firstPart + afterDecimalPlace;
essentially that is:
92/100 = .92
7 + .92 = 7.92

Cannot add/subtract from large doubles in Objective C

I am trying to subtract 1 from a double with this code:
-(NSMutableArray *)getMoreTwitterDataWithMaxID:(double)maxID {
double newestID = (maxID - 1);
NSLog(#"newest ID is %f and maxID is %f", newestID, maxID);
// other code
}
The console is spitting this out:
2012-05-15 11:21:14.693 nearYou[2570:3a03] newest ID is 202429657738522624.000000 and maxID is 202429657738522624.000000
I'm not sure why they aren't subtracting . . .
Any help greatly appreciated!
May be you have reached the limit of the double data type. You can use NSDecimal instead.
You may have reached the limits of the double floating point format. The 64-bit floating point format only has a 52-bit mantissa, meaning it can only hold an integer of 52 bits with any integer accuracy before it uses the exponent. Your number is larger than that so the gap between one integer and the next possible one has grown bigger than 1.

In objective c from a float number I want to sepatate the decimals to do further math work on

I am setting up a calculator that will generate a float number after the user's input. As an example: if the answer generated is 1.75 that would actually represents 1.75 hours. I want to split the answer into two parts to read 1 hr. 45 min which will be more user friendly than .75 of an hour is.
So I need to be able to delete the whole digit(s) (in this example the "1") before the decimal to get a variable value using the .75 --kind of like this:
mIn = (.75 * 60) which would give me the 45 minutes value to put in my...
[NSString stringWithFormat:#"#% hr. #% min", hRs, mIn]; type of statement
Any help on this would be greatly appreciated.
You almost certainly do not want to use a float to store a user-entered number, particularly for a calculator. This will lead to decimal/binary rounding errors that will drive you crazy. You want to use NSDecimalNumber for this kind of work.
The other answers here will work, but you want to replace floor() with decimalNumberByRoundingAccordingToBehavior:. You'll use an NSDecimalNumberHandler with a rounding mode of NSRoundDown and an appropriate scale (probably 2 or 3 for your purposes).
Use floor(floatValue) to get the integer portion, subtract that from the floatValue to get the decimal portion.
Ex:
float floatValue = 1.75;
float integerPortion = floor(floatValue);
float decimalPortion = floatValue - integerPortion;
NSString *timeString = [NSString stringWithFormat:#"%.0f hr. %.0f min", integerPortion, decimalPortion * 60];
NSLog(#"timeString: %#", timeString);
NSLog output:
timeString: 1 hr. 45 min
You can cast the floating value to an int and subtract that from the value or you can floor it.
float time = 1.75;
int minutes = (time - (int)time) * 60; //or (time - floor(time)) * 60;
NSLog(#"Time: %#", [NSString stringWithFormat:#"%d hr. %d min", (int)time, minutes]);

CGFloat addition bug?

I was trying to add some CGFloat values recursively in my program. And I just realized in one particular scenario the total generated was incorrect. To ensure I had nothing wrong in my program logic, I created a simple example of that scenario (see below) and this printed the same wrong value.
CGFloat arr[3] = {34484000,512085280,143011440};
CGFloat sum = 0.0;
sum = arr[0] + arr[1] + arr[2];
NSLog(#"%f",sum);
int arr1[3] = {34484000,512085280,143011440};
int sum1 = 0.0;
sum1 = arr1[0] + arr1[1] + arr1[2];
NSLog(#"%d",sum1);
The first NSLog prints 689580736.000000...while the correct result 689580720. However the second NSLog prints the correct result. I am not sure if this is a bug or if I am doing something wrong.
Thanks,
Murali
CGFloat is a single precision float on 32 bit targets such as iOS - it only has a 23 bit mantissa, i.e. around 6 - 7 significant digits. Use a double precision type if you need greater accuracy.
You should probably read David Goldberg's What Every Computer Scientist Should Know About Floating-Point Arithmetic before proceeding much further with learning to program.

Objective-C: Strange calculation result

I am learning Objective-C and have completed a simple program and got an unexpected result. This program is just a multiplication table test... User inputs the number of iterations(test questions), then inputs answers. That after program displays the number of right and wrong answers, percentage and accepted/failed result.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Welcome to multiplication table test");
int rightAnswers; //the sum of the right answers
int wrongAnswers; //the sum of wrong answers
int combinations; //the number of combinations#
NSLog(#"Please, input the number of test combinations");
scanf("%d",&combinations);
for(int i=0; i<combinations; ++i)
{
int firstInt=rand()%8+1;
int secondInt=rand()%8+1;
int result=firstInt*secondInt;
int answer;
NSLog(#"%d*%d=",firstInt,secondInt);
scanf("%d",&answer);
if(answer==result)
{
NSLog(#"Ok");
rightAnswers++;
}
else
{
NSLog(#"Error");
wrongAnswers++;
}
}
int percent=(100/combinations)*rightAnswers;
NSLog(#"Combinations passed: %d",combinations);
NSLog(#"Answered right: %d times",rightAnswers);
NSLog(#"Answered wrong: %d times",wrongAnswers);
NSLog(#"Completed %d percent",percent);
if(percent>=70)NSLog(#"accepted");
else
NSLog(#"failed");
[pool drain];
return 0;
}
Problem (strange result)
When I input 3 iterations and answer 'em right, i am not getting of 100% right. Getting only
99%. The same count I tried on my iPhone calculator.
100 / 3 = 33.3333333... percentage for one right answer (program displays 33%. The digits after mantissa getting cut off)
33.3333333... * 3=100%
Can someone explain me where I went wrong? Thanx.
This is a result of integer division. When you perform division between two integer types, the result is automatically rounded towards 0 to form an integer. So, integer division of (100 / 3) gives a result of 33, not 33.33.... When you multiply that by 3, you get 99. To fix this, you can force floating point division by changing 100 to 100.0. The .0 tells the compiler that it should use a floating point type instead of an integer, forcing floating point division. As a result, rounding will not occur after the division. However, 33.33... cannot be represented exactly by binary numbers. Because of this, you may still see incorrect results at times. Since you store the result as an integer, rounding down will still occur after the multiplication, which will make it more obvious. If you want to use an integer type, you should use the round function on the result:
int percent = round((100.0 / combinations) * rightAnswers);
This will cause the number to be rounded to the closest integer before converting it to an integer type. Alternately, you could use a floating point storage type and specify a certain number of decimal places to display:
float percent = (100.0 / combinations) * rightAnswers;
NSLog(#"Completed %.1f percent",percent); // Display result with 1 decimal place
Finally, since floating point math will still cause rounding for numbers that can't be represented in binary, I would suggest multiplying by rightAnswers before dividing by combinations. This will increase the chances that the result is representable. For example, 100/3=33.33... is not representable and will be rounded. If you multiply by 3 first, you get 300/3=100, which is representable and will not be rounded.
Ints are integers. They can't represent an arbitrary real number like 1/3. Even floating-point numbers, which can represent reals, won't have enough precision to represent an infinitely repeating decimal like 100/3. You'll either need to use an arbitrary-precision library, use a library that includes rationals as a data type, or just store as much precision as you need and round from there (e.g. make your integer unit hundredths-of-a-percent instead of a single percentage point).
You might want to implement some sort of rounding because 33.333....*3 = 99.99999%. 3/10 is an infinite decimal therefore you need some sort of rounding to occur (maybe at the 3rd decimal place) so that the answer comes out correct. I would say if (num*1000 % 10 >= 5) num += .01 or something along those lines multiply by 100 moves decimal 3 times and then mod returns the 3rd digit (could be zero). You also might only want to round at the end once you sum everything up to avoid errors.
EDIT: Didn't realize you were using integers numbers at the end threw me off, you might want to use double or float (floats are slightly inaccurate past 2 or 3 digits which is OK with what you want).
100/3 is 33. Integer mathematics here.