Rounding big numbers to nearest hundred, float is losing value - ios

I am trying to round big numbers to the nearest 1 hundred, by dividing by 100, rounding and then multiplying by 100.
However, the big number values are losing value when converting to floats.
This is the problem part:
int bigInt = 99222049;
float bigFloat = bigInt / 100.0;
NSLog(#"%d %f", bigInt, bigFloat);
Output:
99222049 992220.500000
Would like it to be:
99222049 992220.49
Sorry if this is a stupid question! Would be grateful for advice. Thanks.

Your basic problem is float rounding. You cannot express arbitrary decimal fractions as floats (or doubles). In binary, 1/10 is 0.00011001100110011... It never terminates, just like 1/3 is 0.33333... in decimal. So you need to do your work in base 10, not base 2, if you want your results to round nicely in base 10. There are two approaches in Cocoa:
You can do your work purely with integer math, no floating point. See Rounding integers to nearest ten or hundred in C for an example of how to do this.
Alternately, since this is ObjC, you can use NSDecimalNumber, which will allow you to perform all your math in base 10.

You need to change your float to a double.
int bigInt = 99222049;
double bigFloat = bigInt / 100.0;
NSLog(#"%u %f", bigInt, bigFloat);
Outputs:
99222049 992220.490000

Change your code to this and the output should show as you desire. I changed the float to a double and .2 before f to show only 2 decimal places.
int bigInt = 99222049;
double bigFloat = bigInt / 100.0;
NSLog(#"%d %.2f", bigInt, bigFloat);
This is what shows in console
99222049 992220.49
I hope this helps, cheers, Jim.

Related

Why multiply two double in dart result in very strange number

Can anyone explain why the result is 252.99999999999997 and not 253? What should be used instead to get 253?
double x = 2.11;
double y = 0.42;
print(((x + y) * 100)); // print 252.99999999999997
I am basically trying to convert a currency value with 2 decimal (ie £2.11) into pence/cent (ie 211p)
Thanks
In short: Because many fractional double values are not precise, and adding imprecise values can give even more imprecise results. That's an inherent property of IEEE-754 floating point numbers, which is what Dart (and most other languages and the CPUs running them) are working with.
Neither of the rational numbers 2.11 and 0.42 are precisely representable as a double value. When you write 2.11 as source code, the meaning of that is the actual double values that is closest to the mathematical number 2.11.
The value of 2.11 is precisely 2.109999999999999875655021241982467472553253173828125.
The value of 0.42 is precisely 0.419999999999999984456877655247808434069156646728515625.
As you can see, both are slightly smaller than the value you intended.
Then you add those two values, which gives the precise double result 2.529999999999999804600747665972448885440826416015625. This loses a few of the last digits of the 0.42 to rounding, and since both were already smaller than 2.11 and 0.42, the result is now even more smaller than 2.53.
Finally you multiply that by 100, which gives the precise result 252.999999999999971578290569595992565155029296875.
This is different from the double value 253.0.
The double.toString method doesn't return a string of the exact value, but it does return different strings for different values, and since the value is different from 253.0, it must return a different string. It then returns a string of the shortest number which is still closer to the result than to the next adjacent double value, and that is the string you see.

Comparison of floats in the Metal Shading Language

Is there an easier way of comparing two floats in the metal shading language?
I'm currently multiplying by 1000 then converting to an int to get an integer comparison.
int r = (int)(color.r * 1000);
int checkColorR = (int)(50.0/255.0 * 1000);
if (r == checkColorR) ...
I'm after something like: Mathf.Approximately in Unity
A common technique is to compare the absolute difference to some desired precision:
if (fabs(color.r - 50.0/255.0) < 1.0/1000.0) ...
You can, of course, define a function for this rather than repeating it all over the place.
Your current technique is bad because it does integer truncation. The two values could be very close, but on either side of an integer, and they would compare as not equal because one would be truncated to the integer below. For example, 4.9999 and 5.0001.

Round floating value to .1 (tens place) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I round a float value to 2 post decimal positions?
Lets say I have a double number of 3.46.
How do I round it to 3.50?
I tried
NSLog(#"res: %.f", round(3.46));
but it return 3.
Do some calculations....
float f=3.46;
float num=f+0.05;//3.51
int intNum=num*10;//35
float floatNum=intNum/10.0;//3.5
NSLog(#"res: %.2f", floatNum); //3.50
Following code may help
i = roundf(10 * i) / 10.0;
where i is your float variable
If you're willing to live with the rounding rules from printf, then the following should suffice when rounding for presentation:
NSLog(#"res: %.1f0", 3.46);
Note that the 0 is just a normal character that is added after the value is formatted to the appropriate number (1) of decimal places. This approach should be usable with [NSString stringWithFormat:] as well.
The original code results in "3" because round always returns an integral value.
YMMV; I don't even use iOS.

Objective C ceil returns wrong value

NSLog(#"CEIL %f",ceil(2/3));
should return 1. However, it shows:
CEIL 0.000000
Why and how to fix that problem? I use ceil([myNSArray count]/3) and it returns 0 when array count is 2.
The same rules as C apply: 2 and 3 are ints, so 2/3 is an integer divide. Integer division truncates so 2/3 produces the integer 0. That integer 0 will then be cast to a double precision float for the call to ceil, but ceil(0) is 0.
Changing the code to:
NSLog(#"CEIL %f",ceil(2.0/3.0));
Will display the result you're expecting. Adding the decimal point causes the constants to be recognised as double precision floating point numbers (and 2.0f is how you'd type a single precision floating point number).
Maudicus' solution works because (float)2/3 casts the integer 2 to a float and C's promotion rules mean that it'll promote the denominator to floating point in order to divide a floating point number by an integer, giving a floating point result.
So, your current statement ceil([myNSArray count]/3) should be changed to either:
([myNSArray count] + 2)/3 // no floating point involved
Or:
ceil((float)[myNSArray count]/3) // arguably more explicit
2/3 evaluates to 0 unless you cast it to a float.
So, you have to be careful with your values being turned to int's before you want.
float decValue = (float) 2/3;
NSLog(#"CEIL %f",ceil(decValue));
==>
CEIL 1.000000
For you array example
float decValue = (float) [myNSArray count]/3;
NSLog(#"CEIL %f",ceil(decValue));
It probably evaluates 2 and 3 as integers (as they are, obviously), evaluates the result (which is 0), and then converts it to float or double (which is also 0.00000). The easiest way to fix it is to type either 2.0f/3, 2/3.0f, or 2.0f/3.0f, (or without "f" if you wish, whatever you like more ;) ).
Hope it helps

Small numbers in Objective C 2.0

I created a calculator class that does basic +,-, %, * and sin, cos, tan, sqrt and other math functions.
I have all the variables of type double, everything is working fine for big numbers, so I can calculate numbers like 1.35E122, but the problem is with extremely small numbers. For example if I do calculation 1/98556321 I get 0 where I would like to get something 1.01464E-8.
Should I rewrite my code so that I only manipulate NSDecimalNumber's and if so, what do I do with sin and cos math functions that accept only double and long double values.
1/98556321
This division gives you 0 because integer division is performed here - the result is an integer part of division. The following line should give you floating point result:
1/(double)98556321
integer/integer is always an integer
So either you convert the upper or the lower number to decimal
(double)1/98556321
or
1/(double)98556321
Which explicitely convert the number to double.
Happy coding....

Resources