digitalmars.D - float equality
- spir (15/15) Feb 19 2011 Hello,
- Simon Buerger (12/23) Feb 19 2011 It is generally a bad idea to use "==" with floats, as most decimals
- bearophile (7/9) Feb 20 2011 I meant to replace the nude FP equality with a function that has the sha...
- Walter Bright (3/11) Feb 20 2011 MISRA is not suggesting having the language silently default to approxim...
- bearophile (10/12) Feb 20 2011 Right. But I am not suggesting that, in what I have suggested there is n...
- so (13/32) Feb 21 2011 I still think "==" should mean the exact equality test and must be
- bearophile (23/34) Feb 21 2011 Everyone in this thread has misunderstood what I have tried to say, so I...
- so (20/46) Feb 21 2011 Why not? A logical flaw on my part or the statement being somewhat harsh...
- bearophile (5/7) Feb 21 2011 I don't know, I am here to learn this too. You have languages like Assem...
- spir (45/57) Feb 22 2011 I understand your position. But I don't share it.
- Kagamin (2/8) Feb 21 2011 Is it safe to assert that noone needs exact FP comparison?
- Robert Jacques (3/14) Feb 21 2011 Nope. if(var == 0) is a common, important and valid test. To say nothing...
- so (9/20) Feb 21 2011 Strange no one mentioned this.
Hello, What do you think of this? unittest { assert(-1.1 + 2.2 == 1.1); // pass assert(-1.1 + 2.2 + 3.3 == 4.4); // pass assert(-1.1 + 3.3 + 2.2 == 4.4); // fail assert(-1.1 + 3.3 == 2.2); // fail } There is approxEquals in stdlib, right; but shouldn't builtin "==" be consistent anyway? Denis -- _________________ vita es estrany spir.wikidot.com
Feb 19 2011
On 19.02.2011 13:06, spir wrote:Hello, What do you think of this? unittest { assert(-1.1 + 2.2 == 1.1); // pass assert(-1.1 + 2.2 + 3.3 == 4.4); // pass assert(-1.1 + 3.3 + 2.2 == 4.4); // fail assert(-1.1 + 3.3 == 2.2); // fail } There is approxEquals in stdlib, right; but shouldn't builtin "==" be consistent anyway? DenisIt is generally a bad idea to use "==" with floats, as most decimals cant be represented exact in binary floating point. That means there is no float for the value "1.1". Though there are exact floats for 0.25, 0.5, 42.125 and so on. The only reason the first two testcases work is, that it is rounded the same way both sides of the "==" but you should not rely on that. Also note, that these calculations are probably done at compile-time, and the compiler is allowed to use a higher precision than at run-time, so you might get different result when you let the user input the numbers. - Krox
Feb 19 2011
Walter:There's a total lack of evidence for that.MISRA-C standard disallows the equality among FP values. I presume they have some serious evidence for their choices, but I don't know such evidence. Today MISRA-C is one of the most serious attempts at fixing the holes in C language to write more reliable code for the industry. MISRA-C standard is sometimes extreme and I don't suggest to follow everything they say, but I suggest to not totally ignore what it says about many C features.1. Roundoff error is not of a fixed magnitude.I meant to replace the nude FP equality with a function that has the shared number of mantissa bits as third required argument. And then perform the normal FP equality using the "is" operator. Regarding FP rounding errors, eventually it will be good to add to Phobos2 a library for Interval FP arithmetic, with trigonometric functions too, etc: http://en.wikipedia.org/wiki/Interval_arithmetic Bye, bearophile
Feb 20 2011
bearophile wrote:MISRA is not suggesting having the language silently default to approximate equality.There's a total lack of evidence for that.MISRA-C standard disallows the equality among FP values. I presume they have some serious evidence for their choices, but I don't know such evidence. Today MISRA-C is one of the most serious attempts at fixing the holes in C language to write more reliable code for the industry. MISRA-C standard is sometimes extreme and I don't suggest to follow everything they say, but I suggest to not totally ignore what it says about many C features.
Feb 20 2011
Walter:MISRA is not suggesting having the language silently default to approximate equality.Right. But I am not suggesting that, in what I have suggested there is nothing silent :-) Given: double x, y; I have suggested in D: x == y => syntax error. x is y => the same FP equality as today. some syntax(x, y, how_much_to_approximate) => approximate equality. Bye, bearophile
Feb 20 2011
On Sun, 20 Feb 2011 14:53:03 +0200, bearophile <bearophileHUGS lycos.com> wrote:Walter:I still think "==" should mean the exact equality test and must be consistent in language. Making something like almostEqual default is far more catastrophic than its current form. It doesn't solve the existing problem and create a basis for new form of problems. If one doesn't know what floating point is and insists on using it, it is his own responsibility to face the consequences.There's a total lack of evidence for that.MISRA-C standard disallows the equality among FP values. I presume they have some serious evidence for their choices, but I don't know such evidence. Today MISRA-C is one of the most serious attempts at fixing the holes in C language to write more reliable code for the industry. MISRA-C standard is sometimes extreme and I don't suggest to follow everything they say, but I suggest to not totally ignore what it says about many C features.1. Roundoff error is not of a fixed magnitude.I meant to replace the nude FP equality with a function that has the shared number of mantissa bits as third required argument. And then perform the normal FP equality using the "is" operator.Regarding FP rounding errors, eventually it will be good to add to Phobos2 a library for Interval FP arithmetic, with trigonometric functions too, etc: http://en.wikipedia.org/wiki/Interval_arithmetic Bye, bearophileIf only interval arithmetic would solve all the problems, i wouldn't hesitate dumping everything about FP. But no, it comes with its shortcomings.
Feb 21 2011
so:I still think "==" should mean the exact equality test and must be consistent in language.Everyone in this thread has misunderstood what I have tried to say, so I will try to explain again, see the bottom of this post. My idea was to turn the "==" operator among FP values into a syntax error (plus other added ideas).Making something like almostEqual default is far more catastrophic than its current form.This problem doesn't exists in my idea.It doesn't solve the existing problem and create a basis for new form of problems.The problems it creates are smaller.If one doesn't know what floating point is and insists on using it, it is his own responsibility to face the consequences.I don't buy this argument.If only interval arithmetic would solve all the problems, i wouldn't hesitate dumping everything about FP. But no, it comes with its shortcomings.I agree that interval arithmetic has its downsides. I have not proposed to replace normal floating point values with intervals. I have suggested to add a Phobos module for interval arithmetic because it's a useful thing to have. --------------------- The little proposal I was thinking about is: 1) Turn the "==" operator into a compile-time syntax error if one or both operands are floating point values. if (x == y) { ==> syntax error 2) The semantic of the "==" is now done by the "is" operator. So if you want exactly this C code: if (x == y) { you use: if (x is y) { 3) Then another built-in function or semantics is added, that is similar to: some_syntax(x, y, an_approximation_level) It takes tree arguments: x, y and a number of bits. Turning the == into a syntax error is done to remember programmers that == among FP values is tricky, and the "is" operator is added because there are some situations where you want an exact comparison and you know what you are doing. This was my idea. I know it doesn't improve the current situation a lot... so I don't expect this to be accepted. But I like to be understood :-) Bye, bearophile
Feb 21 2011
Why not? A logical flaw on my part or the statement being somewhat harsh? Because i don't think it is the former, i will give an example for the latter. I am a self-taught programmer and i too made big mistakes when using FP, probably i still do since it is a strange beast to deal with even if you know all about it. For this reason it is somewhat understandable for people like me failing this kind of traps but can we say same thing for others? Do they have this excuse? Not knowing the fundamental thing about FP and use it?If one doesn't know what floating point is and insists on using it, it is his own responsibility to face the consequences.I don't buy this argument.The little proposal I was thinking about is: 1) Turn the "==" operator into a compile-time syntax error if one or both operands are floating point values. if (x == y) { ==> syntax error 2) The semantic of the "==" is now done by the "is" operator. So if you want exactly this C code: if (x == y) { you use: if (x is y) { 3) Then another built-in function or semantics is added, that is similar to: some_syntax(x, y, an_approximation_level) It takes tree arguments: x, y and a number of bits. Turning the == into a syntax error is done to remember programmers that == among FP values is tricky, and the "is" operator is added because there are some situations where you want an exact comparison and you know what you are doing. This was my idea. I know it doesn't improve the current situation a lot... so I don't expect this to be accepted. But I like to be understood :-) Bye, bearophileOne thing i fail to understand here is, yes i agree "float == float" probably a "code smell" and we can find a workaround for this. But i have to ask, where does it stop? I mean i can just here find you pages and pages of illogical results created with crafted examples using not even floating points but integrals. If you want to make it easier like the case in hand, ignore a fundamental rule and you get tons of examples. All i am trying to say is that if we are not in a position to solve this huge problem with a syntax change, lets just keep it the way it is instead of making yet another inconsistency.
Feb 21 2011
so:Why not?A system language has to allow the programmer to do everything the hardware is capable to do, including comparing floats in the usual way. But in general for a well designed language it's better to clearly denote dangerous/unsafe/bad things, and to make the safer routes the first ones you usually try.where does it stop?I don't know, I am here to learn this too. You have languages like Assembly, SPARK, ATS. They are successful in their niche and for their purposes. They are at the (current) opposites for safety, control, freedom, power, performance, etc. In the area that has those tree languages as vertices (and there are many more possible vertices to choose from) there is a lot of design space for good languages. Bye, bearophile
Feb 21 2011
On 02/21/2011 10:17 PM, so wrote:I understand your position. But I don't share it. The problem is binary floating point representations of numbers introduce a little set of traps due to the fact that they are implicitely supposed to be the type representing "fractional" or real numbers, but they cannot do that in a way that matches our (widely unconscious) intuitions in the domain, themselves (I guess) a by-product of years of manipulation at school. The simple notation "1.1" comes with a huge baggage of pre-existing knowledge by everyone (programmers). We should not blindly make abstraction of that fact, and put the burden on the users' shoulders, without even a honest trial in solving the issue. When a programmer writes: x = 1.1; or x = 1/3.0; the meaning is just that, and refers to all this knowledge. There is in most cases no intention (not even implicite) to use binary floating point numbers, instead to have a representation for the plain arithmetics values as written down. Hope I'm clear. Very few people (ones that have repetedly been caught by the conceptual traps) will have "alarm bell" ring when writing this, and consequently take all appropriate precautions required to avoid subsequenty falling into the traps and... have buggy code. This may be a bit different if the notation did not recall all of that knowledge: x = 1.1f; // alarm bell!? I would advocate that a general-purpose language should use a different representation for ordinary need of fractional/real numbers, one that does not introduce such traps and/or warns about them (via warnongs/errors, like Bearophile's proposal). One possibility may be to use fixed point with a /decimal/ scale factor (the mantissa beeing binary or decimal integer). Other possibilities: true rationals, decimal 'reals'. The issue is indeed any of those solutions has a cost (even more with modern machines having native float artithmetic). But numeric computation intensive apps would just use floats, /explicitely/ (and hopefully correctly). A similar issue is the one of signed <--> unsigned ints. I would just make as default the range of unsigned ints be a subset of signed ones. And let the full range available for people who really need it, to be used explicitely. Anyway, such solutions may not be good for D, beeing (also) a systems programming language in the C line. Still, I think it's worth exploring the topic instead of letting bug-prone features silently sit at the deep core of the language. Denis -- _________________ vita es estrany spir.wikidot.comWhy not? A logical flaw on my part or the statement being somewhat harsh? Because i don't think it is the former, i will give an example for the latter. I am a self-taught programmer and i too made big mistakes when using FP, probably i still do since it is a strange beast to deal with even if you know all about it. For this reason it is somewhat understandable for people like me failing this kind of traps but can we say same thing for others? Do they have this excuse? Not knowing the fundamental thing about FP and use it?If one doesn't know what floating point is and insists on using it, it is his own responsibility to face the consequences.I don't buy this argument.
Feb 22 2011
bearophile Wrote:Jonathan M Davis:Is it safe to assert that noone needs exact FP comparison?The thing is, of course, that actual equality sucks for floating point values.So much, that some people have proposed to deprecate the normal FP equality. MISRA-C disallows them. When you see a == among FP values is often a code smell.
Feb 21 2011
On Mon, 21 Feb 2011 10:15:28 -0500, Kagamin <spam here.lot> wrote:bearophile Wrote:Nope. if(var == 0) is a common, important and valid test. To say nothing of testing for sentinel values.Jonathan M Davis:Is it safe to assert that noone needs exact FP comparison?The thing is, of course, that actual equality sucks for floatingpoint values. So much, that some people have proposed to deprecate the normal FP equality. MISRA-C disallows them. When you see a == among FP values is often a code smell.
Feb 21 2011
On Sat, 19 Feb 2011 14:06:38 +0200, spir <denis.spir gmail.com> wrote:Hello, What do you think of this? unittest { assert(-1.1 + 2.2 == 1.1); // pass assert(-1.1 + 2.2 + 3.3 == 4.4); // pass assert(-1.1 + 3.3 + 2.2 == 4.4); // fail assert(-1.1 + 3.3 == 2.2); // fail } There is approxEquals in stdlib, right; but shouldn't builtin "==" be consistent anyway? DenisStrange no one mentioned this. Problem is not the floating point format in your example. I can do the same with integral numbers, how? int(5) / int(2) => int(2) or int(3)? And why? Answer depends on the rounding mode, if you don't know the given rounding mode for a (machine interpreted) number system you can't say anything. You know the answer because you know the rule. I can say same for the floating points since i know how they work.
Feb 21 2011