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.
Related
I know that storing single value (or double) can not be very precise. so storing for example 125.12 can result in 125.1200074788. now in delphi their is some usefull function like samevalue or comparevalue that take an epsilon as param and say that 125.1200074788 or for exemple 125.1200087952 is equal.
but i often see in code stuff like : if aSingleVar = 0 then ... and this in fact as i see always work. why ? why storing for exemple 0 in a single var keep the exact value ?
Only values that are in form m*2^e, where m and e are integers can be stored in a floating point variable (not all of them though, it depends on precision). 0 has this form, and 125.12 does not, as it equals 3128/25, and 1/25 is not an integer power of 2.
Comparing 125.12 to a single (or double) precision variable will most probably return always False, because a literal 125.12 will be treated as an extended precision number, and no single (or double) precision number would have such a value.
Looks like a good use for the BigDecimals unit by Rudy Velthuis. Millions of decimal places of accuracy and precision.
The goal is to fast extract bit at position N;
So far i've found only this way to do that:
CREATE OR REPLACE FUNCTION test(x int, size int)
RETURNS int AS
$BODY$
DECLARE
y int;
BEGIN
y = get_bit(x::bit(size)>>size-1,size-1);
return y;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
But this says because of bit(size)
invalid input syntax for integer: "size"
So i'm forsed to write size as a constant, for example bit(3)
Is there any way to set bit size dynamically? Alternatively, maybe there are some other ways to extract specific bit of int/text?
You don't need bitfield types for this. To test bit 6 of the value 200:
SELECT 200 & (1<<6) != 0
you binary-AND a value with the 6th bit set, by upshifting 1 by 6 base-2 places, then test to see if the result is nonzero.
Alternately, cast to a suitable bit size based on the integer and use position, though I think there's no reason whatsoever to do that when you can use extremely fast bitwise AND and shifts like above. Because get_bit numbers from the left, and uses a 1-offset instead of 0-offset, you have to take the compliment of 31 (for a 32-bit int) to get the position from the right:
SELECT get_bit(200::bit(32), 31 - 6);
so it's way simpler to just use bitwise operations like the first example.
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.
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
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....