[Issue 13489] Boolean semantics of floating point types should use "<> 0"
https://issues.dlang.org/show_bug.cgi?id=13489 Mathias LANG changed: What|Removed |Added Status|NEW |RESOLVED CC||pro.mathias.l...@gmail.com Resolution|--- |WONTFIX --- Comment #16 from Mathias LANG --- Walter rejected the PR made to fix this. Closing as "WONTFIX". --
[Issue 13489] Boolean semantics of floating point types should use "<> 0"
https://issues.dlang.org/show_bug.cgi?id=13489 Dlang Bot changed: What|Removed |Added Keywords||pull --- Comment #15 from Dlang Bot --- @Geod24 created dlang/dmd pull request #10363 "Fix issue 13489: Boolean semantics of floating point types should handle float" fixing this issue: - Fix issue 13489: Boolean semantics of floating point types should handle float https://github.com/dlang/dmd/pull/10363 --
[Issue 13489] Boolean semantics of floating point types should use "<> 0"
https://issues.dlang.org/show_bug.cgi?id=13489 Stewart Gordonchanged: What|Removed |Added CC||s...@iname.com --- Comment #14 from Stewart Gordon --- (In reply to David Eckardt from comment #0) > ulong calcAmount ( double x ) > in > { > assert(x); // succeeds for NaN > } > body > { > // do calculation with x > return lround(fabs(x)); // returns 9223372036854775808 if x is NaN > } > --- This looks to me like a problem with either lround or fabs, rather than with the boolean semantics of a floating point. Still, I agree that the boolean semantics are an issue. (In reply to Walter Bright from comment #2) > In other words, both of them treat NaN as "TRUE". I fear that if we deviate > from this behavior, we'll get subtly broken code that is written by former > C++ programmers or that is transliterated from C++. Can you give an example of how real-world code might explicitly rely on NaN being boolean true? (In reply to bearophile_hugs from comment #4) > The current D situation seems standard: > > http://stackoverflow.com/questions/9158567/nan-to-bool-conversion-true-or- > false > > http://stackoverflow.com/questions/15686318/why-do-not-a-number-values-equal- > true-when-cast-as-boolean-in-python-numpy The spec snippets pasted there don't mention NaN; as such, it looks to me like an oversight. Furthermore, I have just offered this insight on the C/C++ treatment: But does NaN constitute a value at all? It's similar to NULL in typical database systems. I was explicitly taught that NULL is not a value, but the absence of a value. Unless there's evidence to the contrary, I think we can claim the same about NaN. As such, I argue that this leaves the behaviour of convert NaN to a bool undefined, unless there's something elsewhere in the spec that covers the issue. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 Andrei Alexandrescu and...@erdani.com changed: What|Removed |Added Version|D1 D2 |D2 --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 --- Comment #11 from Don clugd...@yahoo.com.au --- (PS. Amounts like 80,833,756,980 Vietnamese Đồng do happen so limiting them is far from trivial...) Yeah, you should have to check the currency and maintain a table of conversion rates. Not a very promising approach ;-) That's 80 billion, far short of the 9 trillion in the original error. It is essential to have sanity checks on the results of critical calculations. FWIW we advertise some real estate in the €20 million price range. That is 0.4 trillion Đồng. I don't see any reason why the Đồng couldn't collapse even further, and push it into the trillions. We have a long history of our sanity checks being incorrect - the real world is a crazy place! But, back on topic -- I think it is debatable whether assert(NaN) should be false (as originally proposed here), or if it should fail to compile. But I am certain that the current behaviour, that assert(NaN) passes, is wrong. Pretty much all existing code containg assert(f); except where f is known at compile time, is broken code. And this is the point -- it's a place in the language where something that looks completely innocent, is actually a landmine. We can either make it have the behaviour that the author clearly intended, (ie, assert( !(f == 0) ); --- Look Mum, no NCEG operators! ) or we could statically disallow implicit conversion from float to bool unless we can prove that the float isn't NaN. I mean, is NaN true, or is it false? The answer is NO, it isn't! So a sensible mapping from IEEE float to bool is not possible. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 monarchdo...@gmail.com changed: What|Removed |Added CC||monarchdo...@gmail.com --- Comment #12 from monarchdo...@gmail.com --- (In reply to Don from comment #11) But I am certain that the current behaviour, that assert(NaN) passes, is wrong. Agreed. It was my understanding anyways that anything that operates on NaN produces false anyways. I'd expect *both*: assert( NaN); assert(!NaN; to fail, actually, since the fist one is Are you non 0? No and the second is Are you 0? No. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 Dicebot pub...@dicebot.lv changed: What|Removed |Added CC||pub...@dicebot.lv --- Comment #13 from Dicebot pub...@dicebot.lv --- (In reply to monarchdodra from comment #12) (In reply to Don from comment #11) But I am certain that the current behaviour, that assert(NaN) passes, is wrong. Agreed. It was my understanding anyways that anything that operates on NaN produces false anyways. I'd expect *both*: assert( NaN); assert(!NaN; to fail, actually, since the fist one is Are you non 0? No and the second is Are you 0? No. I agree with this. One additional thing to point out is that `assert` has already a precedent of being more than just check for 0 - it calls object invariant. Thus meaning of `assert(object)` is closer to check if this thing is in usable state and NaN is not a usable state by definition. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 --- Comment #8 from David Eckardt david.ecka...@sociomantic.com --- I do strongly suggest that calculations that return money values have sanity checks in them for reasonable dollar values; not just 0, Infinity or NaN checks. Absolutely. It was just an impressing situation where NaN caught me. I don't blame D for not catching this particular bug, and I'm aware there are alternative ways of detecting this bug. My point is: NaN was intentionally chosen as the initial floating point value to detect the common bug of forgetting to initialize a variable (http://dlang.org/faq.html#nan). The standard way to detect bugs is a plain assert(). So assert() should fail with NaN. I suggest the boolean behaviour of 0 because believe it makes more sense in general, is compatible to !=0 for integers and pointers and would make assert() fail with NaN. Having cast(bool)d yield different results than d!=0 to me is very surprising behavior. I agree it can be considered surprising, and that's an essential point of this debate. But at least if d is a negative 0, cast(bool)d is false even though the binary data in d contain a set bit (i.e., if d is a double, cast(bool)*cast(ulong*)d is true). This can be considered surprising, too. On the other hand, by its nature NaN causes many surprises so I believe we can live with a false boolean result if we have the benefit of catching a well known bug. (PS. Amounts like 80,833,756,980 Vietnamese Đồng do happen so limiting them is far from trivial...) --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 --- Comment #9 from Leandro Lucarella leandro.lucare...@sociomantic.com --- (In reply to David Eckardt from comment #8) My point is: NaN was intentionally chosen as the initial floating point value to detect the common bug of forgetting to initialize a variable (http://dlang.org/faq.html#nan). The standard way to detect bugs is a plain assert(). So assert() should fail with NaN. Yeah, this is the key, NaN should behave the same as null, it should explode as soon as it's used. (PS. Amounts like 80,833,756,980 Vietnamese Đồng do happen so limiting them is far from trivial...) Yeah, you should have to check the currency and maintain a table of conversion rates. Not a very promising approach ;-) --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 Ketmar Dark ket...@ketmar.no-ip.org changed: What|Removed |Added CC||ket...@ketmar.no-ip.org --- Comment #3 from Ketmar Dark ket...@ketmar.no-ip.org --- (In reply to Walter Bright from comment #2) Having cast(bool)d yield different results than d!=0 to me is very surprising behavior. for me too. NaN is clearly not 0, so it's 'true'. but maybe compiler should produce warning telling programmer that he is about to summon a dragon? i.e. for implicit converts to boolean, like `if (d)` and `assert(d)` compiler will tell that implicit convertsion of double to boolean leads to undesired results, please use explicit cast(bool). as for '!=' vs ''... i don't know. it's easy to emit a warning, but i can't think out sane method to hush the compiler if != is what i really want. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 bearophile_h...@eml.cc changed: What|Removed |Added CC||bearophile_h...@eml.cc --- Comment #4 from bearophile_h...@eml.cc --- The current D situation seems standard: http://stackoverflow.com/questions/9158567/nan-to-bool-conversion-true-or-false http://stackoverflow.com/questions/15686318/why-do-not-a-number-values-equal-true-when-cast-as-boolean-in-python-numpy --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 Leandro Lucarella leandro.lucare...@sociomantic.com changed: What|Removed |Added CC||leandro.lucarella@sociomant ||ic.com --- Comment #5 from Leandro Lucarella leandro.lucare...@sociomantic.com --- What the relation of signaling NaN and this. Will `if (nan)` raise a signal? Maybe a runtime check is enough. It's clear that the code that raise this problem is buggy, no argue about that, but how to fix it is not the topic of this issue, the topic is trying to find a way to make the bug impossible to even exist, with help from the language :) --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 --- Comment #6 from Leandro Lucarella leandro.lucare...@sociomantic.com --- (In reply to Leandro Lucarella from comment #5) What the relation of signaling NaN and this. Will `if (nan)` raise a signal? Or any following use of nan afterwards, like `lround(fabs(x))`. f the Maybe a runtime check is enough. It's clear that the code that raise this problem is buggy, no argue about that, but how to fix it is not the topic of this issue, the topic is trying to find a way to make the bug impossible to even exist, with help from the language :) --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 yebblies yebbl...@gmail.com changed: What|Removed |Added CC||yebbl...@gmail.com --- Comment #7 from yebblies yebbl...@gmail.com --- (In reply to Walter Bright from comment #2) Having cast(bool)d rewritten to be d0 is also problematic as Don Clugston is a vocal advocate of having the operator removed from D. This is not problematic, the compiler using it internally does not mean it has to be exposed to the user. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 Walter Bright bugzi...@digitalmars.com changed: What|Removed |Added CC||bugzi...@digitalmars.com --- Comment #2 from Walter Bright bugzi...@digitalmars.com --- Consider this C++ code: bool foo(long double a) { return a; } DMC++ generates: fld tbyte ptr 4[ESP] fldz fucompp ST(1),ST fstsw AX sahf jne L13 jp L13 xor EAX,EAX jmp short L18 L13:mov EAX,1 L18:ret and g++ generates: fld tbyte ptr 8[RSP] mov EAX,1 fldz fucomip fstpST setpDL cmovz EAX,DL ret In other words, both of them treat NaN as TRUE. I fear that if we deviate from this behavior, we'll get subtly broken code that is written by former C++ programmers or that is transliterated from C++. Having cast(bool)d yield different results than d!=0 to me is very surprising behavior. Having cast(bool)d rewritten to be d0 is also problematic as Don Clugston is a vocal advocate of having the operator removed from D. Issuing a warning or error for if(d) can be done, but then the user simply rewrites it as if(d!=0) and I'm not sure if anything was accomplished. So I'm not sure what the right answer would be. I do strongly suggest that calculations that return money values have sanity checks in them for reasonable dollar values; not just 0, Infinity or NaN checks. An amount of 9 trillion dollars shouldn't have gotten far. Such checks can find a great many more mistakes than NaNs would. Another possibility is to not use lround(), i.e. make your own lround that asserts that its argument is not NaN. Note that lround() in D just defers to the C one, which is underspecified as to what happens with NaN or Infinity arguments. I would not rely on C's lround() for financial calculations without first checking its argument. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 Andrej Mitrovic andrej.mitrov...@gmail.com changed: What|Removed |Added CC||andrej.mitrov...@gmail.com --- Comment #1 from Andrej Mitrovic andrej.mitrov...@gmail.com --- Also important to note is how easy a refactoring could produce invalid code. If you use integers in your code and if statements, and you decide to switch to floating-point (say to represent a fraction of a second for a time variable) you can easily end up with faulty code like that. --
[Issue 13489] Boolean semantics of floating point types should use 0
https://issues.dlang.org/show_bug.cgi?id=13489 David Eckardt david.ecka...@sociomantic.com changed: What|Removed |Added Keywords||industry --