I checked in VWNC 7.8, and it appears to suffer exactly from same bug than
explained here http://stackoverflow.com/questions/9902968/why-does-math-round0-49999999999999994-return-1 For example, try (0.5d - (2.0d raisedTo: -54)) < 0.5d. (0.5d - (2.0d raisedTo: -54)) rounded See also http://stackoverflow.com/questions/485525/round-for-float-in-c/11074691#11074691 Is it fixed in 7.9? Nicolas _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Nicolas,
I know just about nothing about the details of the rounding of numbers in the IEEE number world. That said, in 7.9: > (0.5d - (2.0d raisedTo: -54)) < 0.5d. true > (0.5d - (2.0d raisedTo: -54)) rounded 1 0.5d < 0.5d false So at this time, 7.9 is the same as 7.8 But I went a bit farther and found the following are interesting answers also: (0.5s - (2.0s raisedTo: -54)) < 0.5s. true (0.5s - (2.0s raisedTo: -54)) rounded 0 0.5s < 0.5s. false But that's must my 0.02s. And So It Goes Sames ______________________________________________________________________ Samuel S. Shuster [|] VisualWorks Engineering, Code Management Project _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Nicolas Cellier
Huh... yeah, that looks like it's messed up... I'll add it to the queue
of things to deal with in the next IEEE work batch. On 7/21/2012 12:56 PM, Nicolas Cellier wrote: > I checked in VWNC 7.8, and it appears to suffer exactly from same bug than > explained here > http://stackoverflow.com/questions/9902968/why-does-math-round0-49999999999999994-return-1 > > For example, try > > (0.5d - (2.0d raisedTo: -54)) < 0.5d. > (0.5d - (2.0d raisedTo: -54)) rounded > > See also > http://stackoverflow.com/questions/485525/round-for-float-in-c/11074691#11074691 > > Is it fixed in 7.9? > > Nicolas > > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
On 07/21/2012 04:08 PM, Andres Valloud wrote:
> (0.5d - (2.0d raisedTo: -54)) rounded On Windows, this answers 1. On Linux, it answers the (correct) 0. Regards, -Martin _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Andres Valloud-6
Nicholas,
This issue has been discussed to death over decades. The answer always comes back to "it is correct by IEEE standards" and the standard sucks. VW 7.5 image with 7.6 VM: (0.5 - (2.0 raisedTo: -54)) < 0.5. false (0.5 - (2.0 raisedTo: -54)) rounded 1 (0.5d - (2.0d raisedTo: -54)) < 0.5d. true (0.5d - (2.0d raisedTo: -54)) rounded 1 ((1/2) - (2 raisedTo: -54)) < (1/2). true ((1/2) - (2 raisedTo: -54)) rounded 0 64-bit GS/S (floats are now always doubles): (0.5 - (2.0 raisedTo: -54)) < 0.5. true (0.5 - (2.0 raisedTo: -54)) rounded 1 ((1/2) - (2 raisedTo: -54)) < (1/2). true ((1/2) - (2 raisedTo: -54)) rounded 0 Floats in VW once seemed to compensate for IEEE float imprecision like magic to give a logically correct answer. Not anymore. Both GS and VW are now fully compliant to the standard and can't give a more correct answer than C. The way GS displays floats is usually irritating, but it is nice that it reveals why the computations answered as they had: (0.5 - (2.0 raisedTo: -54)) 4.9999999999999994E-01 0.5 5.0000000000000000E-01 This returns the noise from 64-bit GS floats: limitOfDecimalPrecision "Extension used to avoid float imprecision noise. Answer a value beyond which would be considered noise for this float implementation." 0.0 == self ifTrue: [^0.0]. "^10.0 raisedTo: (self abs log10 asInteger - 13)." "Same as above, but method becomes 28% faster." ^#( 1.0E-29 1.0E-28 1.0E-27 1.0E-26 1.0E-25 1.0E-24 1.0E-23 1.0E-22 1.0E-21 1.0E-20 1.0E-19 1.0E-18 1.0E-17 1.0E-16 1.0E-15 1.0E-14 1.0E-13 1.0E-12 1.0E-11 1.0E-10 1.0E-09 1.0E-08 1.0E-07 1.0E-06 1.0E-05 1.0E-04 1.0E-03 1.0E-02 1.0E-01 1.0E-00 1.0E+01 1.0E+02 1.0E+03 ) at: 30 + (self abs log10 asInteger - 13). This shows identical precision limits for the two values above: (0.5 - (2.0 raisedTo: -54)) limitOfDecimalPrecision 1.0000000000000000E-13 0.5 limitOfDecimalPrecision 1.0000000000000000E-13 So then just round the to the limit of precision and be done with it: roundoff "Extension by Paul Baumann 2012.03.16. Answer a 'unit roundoff' of the float imprecision (machine epsilon) that the receiver may carry from the previous calculation. It attempts to return a value that would be equal to a double created from string/compiled float value (like '0.1' asFloat). To understand the problem read: http://en.wikipedia.org/wiki/Floating_point 0.1 = ('0.1' asFloat). true 10.0 = (0.1 + 9.9). true 0.1 = (10.0 - 9.9). false 0.1 = (10.0 - 9.9) roundoff. true (0.1 - 9.9) = ((10.0 - 9.9) - 9.9). true (0.1 - 9.9) = ((10.0 - 9.9) - 9.9) roundoff. true (10 - (99 /10)) = (10.0 - 9.9). false (10 - (99 /10)) = (10.0 - 9.9) roundoff. true (10.0 - (99 /10)) = (10.0 - 9.9) roundoff. false (10.0 - (99 /10)) roundOff = (10.0 - 9.9) roundoff. true " 0.0 == self ifTrue: [^0.0]. ^self roundTo: self limitOfDecimalPrecision Using the #roundoff method now gives: (0.5 - (2.0 raisedTo: -54)) roundoff 5.0000000000000000E-01 0.5 roundoff 5.0000000000000000E-01 Looks good, but not a perfect solution though. Incremental imprecision that can't be reliably cut after it is introduced. It is impractical to have all the application code roundoff from operations. I accept that the code works according to IEEE standards and that floats are a bad choice for most applications. IEEE floats are more for efficiency than precision. At some point you end up changing to something that gives a useful answer. Paul Baumann -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Andres Valloud Sent: Saturday, July 21, 2012 19:08 To: [hidden email] Subject: Re: [vwnc] [BUG] round a Float Huh... yeah, that looks like it's messed up... I'll add it to the queue of things to deal with in the next IEEE work batch. On 7/21/2012 12:56 PM, Nicolas Cellier wrote: > I checked in VWNC 7.8, and it appears to suffer exactly from same bug than > explained here > http://stackoverflow.com/questions/9902968/why-does-math-round0-49999999999999994-return-1 > > For example, try > > (0.5d - (2.0d raisedTo: -54)) < 0.5d. > (0.5d - (2.0d raisedTo: -54)) rounded > > See also > http://stackoverflow.com/questions/485525/round-for-float-in-c/11074691#11074691 > > Is it fixed in 7.9? > > Nicolas > > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Paul Baumann <paul.baumann <at> theice.com> writes:
> > Nicholas, > > This issue has been discussed to death over decades. The answer always comes back to "it is correct by IEEE > standards" and the standard sucks. > > VW 7.5 image with 7.6 VM: > > (0.5 - (2.0 raisedTo: -54)) < 0.5. > false > (0.5 - (2.0 raisedTo: -54)) rounded > 1 > > (0.5d - (2.0d raisedTo: -54)) < 0.5d. > true > (0.5d - (2.0d raisedTo: -54)) rounded > 1 > > ((1/2) - (2 raisedTo: -54)) < (1/2). > true > ((1/2) - (2 raisedTo: -54)) rounded > 0 > > 64-bit GS/S (floats are now always doubles): > > (0.5 - (2.0 raisedTo: -54)) < 0.5. > true > (0.5 - (2.0 raisedTo: -54)) rounded > 1 > > ((1/2) - (2 raisedTo: -54)) < (1/2). > true > ((1/2) - (2 raisedTo: -54)) rounded > 0 > > Floats in VW once seemed to compensate for IEEE float imprecision like magic > answer. Not anymore. Both GS and VW are now fully compliant to the standard and can't give a more correct > answer than C. > Hi Paul, if you open a final draft of ISO/IEC 10967-2 standard, http://www.open-std.org/jtc1/sc22/wg11/docs/n462.pdf for example, then you'll find in §5.2.4 a definition of float rounding function. rounding_F(x) = round(x), where round is the exact mathematical function. The case of exact tie might be implementation defined (the function nearest_F is implementation defined as described in §5.2.1, but I did not find the exact definition of round in the draft). So round(0.5) might be 0 or 1 depending on implementation (away from zero, or unbiased, generally to nearest even). But for the predecessor of 0.5, no doubt, the result MUST be zero if you comply to the standard... C99 function round() and C++ 2011 round() are compliant, if you have a recent gcc, you can check with printf( "%f\n",round(0.49999999999999994)); Also note from appendix B.5.2.4, the rounding function is symmetric, rounding_F(x) = neg_F(rounding_F(neg_F(x))) Though, in Smalltalk, we rather implement rounding_F->I(x), and that's a good thing because we don't have to deal with negative zeroes. Of course, all this is quite germane and may not matter for a majority of us, but there is no reason to go against the standards: 1) there is no reason why rounding would be inexact; 2) beside, the fact that some floating point operation are not exact is not a license to spoil the precision gratuitously; 3) the only reason to let the precision degrade is to avoid very costly calculus, which is again not the case for rounding. Current status is just the conjunction of ignorance and laziness (I say laziness because floor(x+copysign(0.5,x)) is a cheap and easy solution). After this post, I hope we can't invoke ignorance again, only laziness remains. So if GS is not compliant, i invite you to open an issue as well... Cheers Nicolas _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Andres Valloud-6
This is fixed now, and should be included in the development 7.10 builds
shortly. On 7/21/2012 4:08 PM, Andres Valloud wrote: > Huh... yeah, that looks like it's messed up... I'll add it to the queue > of things to deal with in the next IEEE work batch. > > On 7/21/2012 12:56 PM, Nicolas Cellier wrote: >> I checked in VWNC 7.8, and it appears to suffer exactly from same bug than >> explained here >> http://stackoverflow.com/questions/9902968/why-does-math-round0-49999999999999994-return-1 >> >> For example, try >> >> (0.5d - (2.0d raisedTo: -54)) < 0.5d. >> (0.5d - (2.0d raisedTo: -54)) rounded >> >> See also >> http://stackoverflow.com/questions/485525/round-for-float-in-c/11074691#11074691 >> >> Is it fixed in 7.9? >> >> Nicolas >> >> _______________________________________________ >> vwnc mailing list >> [hidden email] >> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc >> > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Martin McClure-3
Just looking at old email here... this is fixed now.
On 7/24/12 4:47 PM, Martin McClure wrote: > On 07/21/2012 04:08 PM, Andres Valloud wrote: >> (0.5d - (2.0d raisedTo: -54)) rounded > > On Windows, this answers 1. > On Linux, it answers the (correct) 0. > > Regards, > > -Martin > vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Free forum by Nabble | Edit this page |