Best way to compare CGFloats
Hello, I am stuck with floats (doubles, to be precise) comparison. In part of my app, I am dealing with NSPoint components (x, y) comparison. On 32bit architecture NSPoint components are floats, and direct comparison ( float1 == float2 ) works fine. But on 64bit, they are doubles and '==' does not work due to precision. Lets take an example: C and D are NSPoints. Lets say C is (1.000444089209850063, whatever) and D is (1.00, whatever). If my code is: if (C.x == D.x) thenDoSomething; , then thenDoSomething is not called. Of course. But on my needs, float is more than enough for precision. So question is, what is the most efficient (performance side) and simplest (coding side) way to compare those bastards? At the moment I am thinking about: a) BOOL _floatsOrDoublesAreEqual = ( (float)C.x == (float)D.x); b) BOOL _floatsOrDoublesAreEqual = ( fabs(C.x - D.x) = _epsilon ); , where _epsilon is something like 0.0001. Regards, Rimas M. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats
I usually use fabs() and compare to some small number for things like this, it explicitly says what your tolerance for 'same' is and if your points are going through a series of calculations, it's easy to get them to differ in the lower order bits however you cast them. On 30-Jun-2010, at 4:35 PM, Rimas M. wrote: Hello, I am stuck with floats (doubles, to be precise) comparison. In part of my app, I am dealing with NSPoint components (x, y) comparison. On 32bit architecture NSPoint components are floats, and direct comparison ( float1 == float2 ) works fine. But on 64bit, they are doubles and '==' does not work due to precision. Lets take an example: C and D are NSPoints. Lets say C is (1.000444089209850063, whatever) and D is (1.00, whatever). If my code is: if (C.x == D.x) thenDoSomething; , then thenDoSomething is not called. Of course. But on my needs, float is more than enough for precision. So question is, what is the most efficient (performance side) and simplest (coding side) way to compare those bastards? At the moment I am thinking about: a) BOOL _floatsOrDoublesAreEqual = ( (float)C.x == (float)D.x); b) BOOL _floatsOrDoublesAreEqual = ( fabs(C.x - D.x) = _epsilon ); , where _epsilon is something like 0.0001. Regards, Rimas M. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/rols%40rols.org This email sent to r...@rols.org ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats
Le 30 juin 2010 à 10:35, Rimas M. a écrit : Hello, I am stuck with floats (doubles, to be precise) comparison. In part of my app, I am dealing with NSPoint components (x, y) comparison. On 32bit architecture NSPoint components are floats, and direct comparison ( float1 == float2 ) works fine. But on 64bit, they are doubles and '==' does not work due to precision. Lets take an example: C and D are NSPoints. Lets say C is (1.000444089209850063, whatever) and D is (1.00, whatever). If my code is: if (C.x == D.x) thenDoSomething; , then thenDoSomething is not called. Of course. But on my needs, float is more than enough for precision. So question is, what is the most efficient (performance side) and simplest (coding side) way to compare those bastards? At the moment I am thinking about: a) BOOL _floatsOrDoublesAreEqual = ( (float)C.x == (float)D.x); b) BOOL _floatsOrDoublesAreEqual = ( fabs(C.x - D.x) = _epsilon ); , where _epsilon is something like 0.0001. You should not rely on the fact that it works with float. Comparing floating point value is never safe. So, as the solution a does not solve the problem (you cannot safely compare floating point value), I would choose the b. -- Jean-Daniel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats
On 30 Jun 2010, at 09:35, Rimas M. wrote: So question is, what is the most efficient (performance side) and simplest (coding side) way to compare those bastards? At the moment I am thinking about: a) BOOL _floatsOrDoublesAreEqual = ( (float)C.x == (float)D.x); b) BOOL _floatsOrDoublesAreEqual = ( fabs(C.x - D.x) = _epsilon ); , where _epsilon is something like 0.0001. fabs is the right way to do this in most cases, *but* with co-ordinate values it may be that you are actually more interested in the distance of one point from the other---i.e. you might in fact be interested in CGFloat dx = C.x - D.x, dy = C.y - D.y; BOOL pointsAreEqual = (dx * dx + dy * dy) epsilonSquared; It rather depends on what you want, and that's going to differ from one application to another. Kind regards, Alastair. -- http://alastairs-place.net ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats
Thanks everyone for answers. Now situation is more clear. On Wed, Jun 30, 2010 at 12:14 PM, Alastair Houghton alast...@alastairs-place.net wrote: fabs is the right way to do this in most cases, *but* with co-ordinate values it may be that you are actually more interested in the distance of one point from the other---i.e. you might in fact be interested in CGFloat dx = C.x - D.x, dy = C.y - D.y; BOOL pointsAreEqual = (dx * dx + dy * dy) epsilonSquared; It rather depends on what you want, and that's going to differ from one application to another. In my case I am interested in x's and y's comparison. Not points as themselves. But your suggestion gave me another question, which I have never thought about before - how NSEqualPoints, ...Rects etc works? I guess they *must* be safe to use, because NSPoint, NSRect etc relies on floats/doubles. Or they uses the same '==' and are TRUE only if points/rects are *really* equal? Best Regards, Rimas M. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats
On 30 Jun 2010, at 10:46, Rimas M. wrote: In my case I am interested in x's and y's comparison. Not points as themselves. But your suggestion gave me another question, which I have never thought about before - how NSEqualPoints, ...Rects etc works? I guess they *must* be safe to use, because NSPoint, NSRect etc relies on floats/doubles. Or they uses the same '==' and are TRUE only if points/rects are *really* equal? I think they test for exact equality. Whether that's documented or not I'm not certain, but disassembling those functions appears to support that conclusion. Kind regards, Alastair. -- http://alastairs-place.net ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats
On Wed, Jun 30, 2010 at 1:06 PM, Alastair Houghton alast...@alastairs-place.net wrote: I think they test for exact equality. Whether that's documented or not I'm not certain, but disassembling those functions appears to support that conclusion. I see. Hope that will not cause any unexpected problems. For now I am going to use: #define cDefaultFloatComparisonEpsilon 0.0001 #define cEqualFloats(f1, f2, epsilon) ( fabs( (f1) - (f2) ) epsilon ) #define cNotEqualFloats(f1, f2, epsilon)( !cEqualFloats(f1, f2, epsilon) ) Thank you for your help. Regards, Rimas M. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats (Rick B.)
I am stuck with floats (doubles, to be precise) comparison. Machine 'real-numbers' such as floats and doubles should be thought of as intervals or neighborhoods near the mathematical number. Tests for 'equality' of machine reals should never use machine equality '==' operators. 'Equality' of two machine reals , in this case, means that the two numbers are separated by a distance less than some small number, such as '(fabs(a-b) epsilon)'. Exactly what the value of epsilon should be gets a little tricky. Hope that I am not being too pedantic but imo you should never test for 'equality' ('==') when using machine real data types. Rick B. *- * Stop spam before it gets to your mailbox! Support blocklists. * I use http://www.spamcop.net/. * my PGP key id: 0x63fa758 keyserver: http://keyserver1.pgp.com */ ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats (Rick B.)
On 30 Jun 2010, at 15:56, Frederick Bartram wrote: Hope that I am not being too pedantic but imo you should never test for 'equality' ('==') when using machine real data types. Sometimes you really do want binary equivalence, and in that case == may be the right thing to use. Normally, though, you're quite right, you need to be careful with floating point comparisons (not just equality tests, actually; sometimes for greater-than or less-than comparisons you might want two floats to be un-ordered if they're close in value). I thought it'd be useful to link to the excellent What Every Computer Scientist Should Know About Floating-Point Arithmetic, since that's usually the best thing to give to people who are worrying about this kind of thing: http://dlc.sun.com/pdf/800-7895/800-7895.pdf http://docs.sun.com/source/806-3568/ncg_goldberg.html Anyone who hasn't read it should. Kind regards, Alastair. -- http://alastairs-place.net ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats (Rick B.)
On Wed, Jun 30, 2010 at 11:11 AM, Alastair Houghton alast...@alastairs-place.net wrote: On 30 Jun 2010, at 15:56, Frederick Bartram wrote: Hope that I am not being too pedantic but imo you should never test for 'equality' ('==') when using machine real data types. Sometimes you really do want binary equivalence, and in that case == may be the right thing to use. While we're being pedantic, note that == is not always the same as binary equivalence. For example, 0.0 == -0.0, and x != x when x = NAN. Using == can make sense when you know that your values are exact integers, which is not an uncommon scenario, but neither is it the usual one. Mike ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best way to compare CGFloats (Rick B.)
On 30 Jun 2010, at 17:37, Michael Ash wrote: While we're being pedantic, note that == is not always the same as binary equivalence. For example, 0.0 == -0.0, and x != x when x = NAN. That's a good point. I spoke inaccurately. Using == can make sense when you know that your values are exact integers, which is not an uncommon scenario, but neither is it the usual one. It may also make sense sometimes with floating point values. An example might be where you have an object that you're using as the key for an NSDictionary; in that case, your -isEqual: method may well want to do a proper equality test. These are, however, special situations. Kind regards, Alastair. -- http://alastairs-place.net ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com