Hi all,
i want to compare two small arbitrary floats such as: -3.81964e-13 = -3.55671e-13 --> false but I only want the answer to be false if the difference between the floats is too large. So rather than taking the difference and comparing that to my limit, I want to round or truncate the floats to: -3.0e-13 = -3.0e-13 --> true OR -4.0e-13 = -4.0e-13 --> true I need a way to consistently tranform the numbers without retaining the actual numbers. a := (-3.81964e-13 asFixedPoint: 13) --> -0.0000000000004s b := (-3.55671e-13 asFixedPoint: 13) --> -0.0000000000004s but (a = b) --> false, because it is only changing the representation, not the object itself. So I am having some trouble wrapping my head around how to permanently change the number or how to compare the representations only or how to create a new number with less precision. Any help would be appreciated. thanks Adam _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
On 2014-04-25 2:14 PM, Dennis Smith wrote: > Instead of rounding or truncating which may or may not do exactly what > you want, why not look at the difference ... > > diff := (a - b) abs. > > Now you can check 'diff' either for some absolute max difference, or > as a percentage of one of the values ... > > ^diff < (a abs * 0.1) > > > On 2014-04-25 2:03 PM, Adam Crumpton wrote: >> Hi all, >> >> i want to compare two small arbitrary floats such as: >> >> -3.81964e-13 = -3.55671e-13 --> false >> >> but I only want the answer to be false if the difference between the >> floats is too large. >> >> So rather than taking the difference and comparing that to my limit, >> I want to round or truncate the floats to: >> >> -3.0e-13 = -3.0e-13 --> true OR >> -4.0e-13 = -4.0e-13 --> true >> >> I need a way to consistently tranform the numbers without retaining >> the actual numbers. >> >> a := (-3.81964e-13 asFixedPoint: 13) --> -0.0000000000004s >> b := (-3.55671e-13 asFixedPoint: 13) --> -0.0000000000004s >> >> but (a = b) --> false, because it is only changing the >> representation, not the object itself. >> >> So I am having some trouble wrapping my head around how to >> permanently change the number or how to compare the representations >> only or how to create a new number with less precision. Any help >> would be appreciated. >> >> thanks >> Adam >> _______________________________________________ >> vwnc mailing list >> [hidden email] >> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > -- Dennis Smith Cherniak Software Development Corporation Phone 416.798.7948 ext 314 Email [hidden email] _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Adam Crumpton
Instead of rounding or truncating which may or may not do exactly what
you want, why not look at the difference ... diff := (a - b) abs. Now you can check 'diff' either for some absolute max difference, or as a percentage of one of the values ... ^diff < (a abs * 0.1) On 2014-04-25 2:03 PM, Adam Crumpton wrote: > Hi all, > > i want to compare two small arbitrary floats such as: > > -3.81964e-13 = -3.55671e-13 --> false > > but I only want the answer to be false if the difference between the > floats is too large. > > So rather than taking the difference and comparing that to my limit, I > want to round or truncate the floats to: > > -3.0e-13 = -3.0e-13 --> true OR > -4.0e-13 = -4.0e-13 --> true > > I need a way to consistently tranform the numbers without retaining > the actual numbers. > > a := (-3.81964e-13 asFixedPoint: 13) --> -0.0000000000004s > b := (-3.55671e-13 asFixedPoint: 13) --> -0.0000000000004s > > but (a = b) --> false, because it is only changing the representation, > not the object itself. > > So I am having some trouble wrapping my head around how to permanently > change the number or how to compare the representations only or how to > create a new number with less precision. Any help would be appreciated. > > thanks > Adam > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc -- Dennis Smith Cherniak Software Development Corporation Phone 416.798.7948 ext 314 Email [hidden email] _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Adam Crumpton
That was my first idea, but I don't know what the ideal max difference
should be and it really doesn't give me what I want. for now, I am using the absolute value of the exponent as the length of my FixedPoint, printing the result, and then creating a Float from that string. Then I am adding all of the values to a Bag and getting the tallies. And on top of that there are many such bags that need to be compared with each other. So I was hoping that I was ignorant of method of round or truncating, that was smalltalkish and elegant, because if the two numbers are similar enough, then I need to keep them but only at their generalized precision. I need to make them truly equal. So to recap: I want to tranform a small float into a less small float (-3.81964e-13 --> -4.0e-13) and I want to keep the less small float for tallying and comparing with other less small floats. And I want it to be elegant. thanks, Adam On 4/25/14, 1:14 PM, Dennis Smith wrote: > Instead of rounding or truncating which may or may not do exactly what > you want, why not look at the difference ... > > diff := (a - b) abs. > > Now you can check 'diff' either for some absolute max difference, or > as a percentage of one of the values ... > > ^diff < (a abs * 0.1) > > > On 2014-04-25 2:03 PM, Adam Crumpton wrote: >> Hi all, >> >> i want to compare two small arbitrary floats such as: >> >> -3.81964e-13 = -3.55671e-13 --> false >> >> but I only want the answer to be false if the difference between the >> floats is too large. >> >> So rather than taking the difference and comparing that to my limit, >> I want to round or truncate the floats to: >> >> -3.0e-13 = -3.0e-13 --> true OR >> -4.0e-13 = -4.0e-13 --> true >> >> I need a way to consistently tranform the numbers without retaining >> the actual numbers. >> >> a := (-3.81964e-13 asFixedPoint: 13) --> -0.0000000000004s >> b := (-3.55671e-13 asFixedPoint: 13) --> -0.0000000000004s >> >> but (a = b) --> false, because it is only changing the >> representation, not the object itself. >> >> So I am having some trouble wrapping my head around how to >> permanently change the number or how to compare the representations >> only or how to create a new number with less precision. Any help >> would be appreciated. >> >> thanks >> Adam >> _______________________________________________ >> 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 |
Adam,
You're bumping up against a basic characteristic of floating point numbers, independent of Smalltalk. A good discussion of this can be found here: http://parashift.com/c++-faq/floating-point-arith.html On 4/25/14, 1:23 PM, Adam Crumpton
wrote:
That was my first idea, but I don't know what the ideal max difference should be and it really doesn't give me what I want. for now, I am using the absolute value of the exponent as the length of my FixedPoint, printing the result, and then creating a Float from that string. Then I am adding all of the values to a Bag and getting the tallies. And on top of that there are many such bags that need to be compared with each other. So I was hoping that I was ignorant of method of round or truncating, that was smalltalkish and elegant, because if the two numbers are similar enough, then I need to keep them but only at their generalized precision. I need to make them truly equal. So to recap: _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Adam Crumpton
Adam,
Small floats in Smalltalk had originally been able to solve basic math problems like (0.4 + 0.3 + 0.2 + 0.1 = 1.0). Doubles came to Smalltalk with the implementation of C, so that we can now quickly compute approximations of the correct answer. This answers false because doubles are used (0.4d + 0.3d + 0.2d + 0.1d = 1.0d). Perhaps what you are looking for is a way to cut off the machine epsilon (http://en.wikipedia.org/wiki/Floating_point) to normalize floats. The epsilon depends on the float implementation, so "13" shown below may not be what is required for a VW double (it probably is though). The code below was for 64-bit GS/S, so for VW you might need to put "d" after each float in the code to tell the compiler you want it to be compiled as a double. limitOfDecimalPrecision "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). isMultipleOf: increment " 4.6 \\ 0.05 = 0 false 4.6 isMultipleOf: 0.05 true " ^(self - (self roundTo: increment)) abs <= self limitOfDecimalPrecision shouldEqual: anotherFloat "This does a comparision that compensates for float imprecision. " " (-1.4000000000000001E+00 = -1.4) false" " (-1.4000000000000001E+00 shouldEqual: -1.4) true" 0.0 = anotherFloat ifTrue: [^0.0 = self]. ^(self / anotherFloat) isMultipleOf: 1.0 The #shouldEqual: was my stab at reusing the machine epsilon tests for comparison. I don't recall if this was the implementation that I had later discovered to not pass every test. Perhaps it will give some ideas though. I'm told that other languages have frameworks to adjust for this standard of inaccuracy. Best thing you can do now is to use something other than a float. Paul Baumann -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Adam Crumpton Sent: Friday, April 25, 2014 15:23 To: VW NC Subject: [vwnc] transforming floats [was: comparing floats] That was my first idea, but I don't know what the ideal max difference should be and it really doesn't give me what I want. for now, I am using the absolute value of the exponent as the length of my FixedPoint, printing the result, and then creating a Float from that string. Then I am adding all of the values to a Bag and getting the tallies. And on top of that there are many such bags that need to be compared with each other. So I was hoping that I was ignorant of method of round or truncating, that was smalltalkish and elegant, because if the two numbers are similar enough, then I need to keep them but only at their generalized precision. I need to make them truly equal. So to recap: I want to tranform a small float into a less small float (-3.81964e-13 --> -4.0e-13) and I want to keep the less small float for tallying and comparing with other less small floats. And I want it to be elegant. thanks, Adam On 4/25/14, 1:14 PM, Dennis Smith wrote: > Instead of rounding or truncating which may or may not do exactly what > you want, why not look at the difference ... > > diff := (a - b) abs. > > Now you can check 'diff' either for some absolute max difference, or > as a percentage of one of the values ... > > ^diff < (a abs * 0.1) > > > On 2014-04-25 2:03 PM, Adam Crumpton wrote: >> Hi all, >> >> i want to compare two small arbitrary floats such as: >> >> -3.81964e-13 = -3.55671e-13 --> false >> >> but I only want the answer to be false if the difference between the >> floats is too large. >> >> So rather than taking the difference and comparing that to my limit, >> I want to round or truncate the floats to: >> >> -3.0e-13 = -3.0e-13 --> true OR >> -4.0e-13 = -4.0e-13 --> true >> >> I need a way to consistently tranform the numbers without retaining >> the actual numbers. >> >> a := (-3.81964e-13 asFixedPoint: 13) --> -0.0000000000004s >> b := (-3.55671e-13 asFixedPoint: 13) --> -0.0000000000004s >> >> but (a = b) --> false, because it is only changing the >> representation, not the object itself. >> >> So I am having some trouble wrapping my head around how to >> permanently change the number or how to compare the representations >> only or how to create a new number with less precision. Any help >> would be appreciated. >> >> thanks >> Adam >> _______________________________________________ >> 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 |
Guys, just look at LimitedPrecision>>isWithin:ulpsOf:.
On 4/25/14 13:45 , Paul Baumann wrote: > Adam, > > Small floats in Smalltalk had originally been able to solve basic math problems like (0.4 + 0.3 + 0.2 + 0.1 = 1.0). Doubles came to Smalltalk with the implementation of C, so that we can now quickly compute approximations of the correct answer. This answers false because doubles are used (0.4d + 0.3d + 0.2d + 0.1d = 1.0d). > > Perhaps what you are looking for is a way to cut off the machine epsilon (http://en.wikipedia.org/wiki/Floating_point) to normalize floats. The epsilon depends on the float implementation, so "13" shown below may not be what is required for a VW double (it probably is though). The code below was for 64-bit GS/S, so for VW you might need to put "d" after each float in the code to tell the compiler you want it to be compiled as a double. > > limitOfDecimalPrecision > "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). > > isMultipleOf: increment > " 4.6 \\ 0.05 = 0 > false > 4.6 isMultipleOf: 0.05 > true > " > ^(self - (self roundTo: increment)) abs <= self limitOfDecimalPrecision > > shouldEqual: anotherFloat > "This does a comparision that compensates for float imprecision. " > " (-1.4000000000000001E+00 = -1.4) false" > " (-1.4000000000000001E+00 shouldEqual: -1.4) true" > > 0.0 = anotherFloat ifTrue: [^0.0 = self]. > ^(self / anotherFloat) isMultipleOf: 1.0 > > The #shouldEqual: was my stab at reusing the machine epsilon tests for comparison. I don't recall if this was the implementation that I had later discovered to not pass every test. Perhaps it will give some ideas though. I'm told that other languages have frameworks to adjust for this standard of inaccuracy. Best thing you can do now is to use something other than a float. > > Paul Baumann > > > -----Original Message----- > From: [hidden email] [mailto:[hidden email]] On Behalf Of Adam Crumpton > Sent: Friday, April 25, 2014 15:23 > To: VW NC > Subject: [vwnc] transforming floats [was: comparing floats] > > That was my first idea, but I don't know what the ideal max difference should be and it really doesn't give me what I want. for now, I am using the absolute value of the exponent as the length of my FixedPoint, printing the result, and then creating a Float from that string. Then I am adding all of the values to a Bag and getting the tallies. And on top of that there are many such bags that need to be compared with each other. So I was hoping that I was ignorant of method of round or truncating, that was smalltalkish and elegant, because if the two numbers are similar enough, then I need to keep them but only at their generalized precision. I need to make them truly equal. So to recap: > > I want to tranform a small float into a less small float (-3.81964e-13 > --> -4.0e-13) and I want to keep the less small float for tallying and > comparing with other less small floats. And I want it to be elegant. > > thanks, > Adam > > > On 4/25/14, 1:14 PM, Dennis Smith wrote: >> Instead of rounding or truncating which may or may not do exactly what >> you want, why not look at the difference ... >> >> diff := (a - b) abs. >> >> Now you can check 'diff' either for some absolute max difference, or >> as a percentage of one of the values ... >> >> ^diff < (a abs * 0.1) >> >> >> On 2014-04-25 2:03 PM, Adam Crumpton wrote: >>> Hi all, >>> >>> i want to compare two small arbitrary floats such as: >>> >>> -3.81964e-13 = -3.55671e-13 --> false >>> >>> but I only want the answer to be false if the difference between the >>> floats is too large. >>> >>> So rather than taking the difference and comparing that to my limit, >>> I want to round or truncate the floats to: >>> >>> -3.0e-13 = -3.0e-13 --> true OR >>> -4.0e-13 = -4.0e-13 --> true >>> >>> I need a way to consistently tranform the numbers without retaining >>> the actual numbers. >>> >>> a := (-3.81964e-13 asFixedPoint: 13) --> -0.0000000000004s >>> b := (-3.55671e-13 asFixedPoint: 13) --> -0.0000000000004s >>> >>> but (a = b) --> false, because it is only changing the >>> representation, not the object itself. >>> >>> So I am having some trouble wrapping my head around how to >>> permanently change the number or how to compare the representations >>> only or how to create a new number with less precision. Any help >>> would be appreciated. >>> >>> thanks >>> Adam >>> _______________________________________________ >>> 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 > . > vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Adam Crumpton
On 04/25/2014 12:23 PM, Adam Crumpton wrote:
> I want to tranform a small float into a less small float (-3.81964e-13 > --> -4.0e-13) and I want to keep the less small float for tallying and > comparing with other less small floats. Keep in mind that floats are represented in binary, and that numbers such as -4.0e-13 that look "simple" in decimal notation are not exactly representable as floats. If you want to round or truncate a float for comparison, you might want to do the rounding or truncating in binary to some fixed number of bits of precision. For instance, to truncate a normal 32-bit Float on a little-endian platform to 16 significant bits (reducing the precision by 8 bits): | truncatedFloat | truncatedFloat := inputFloat copy. truncatedFloat basicAt: 1 put: 0 > And I want it to be elegant. Well, I can't claim the above is particularly elegant, but it does seem simpler than what you are currently doing. One way to increase elegance might be to use a subclass of Bag (ApproximateFloatBag, perhaps) that knows to truncate each instance of Float that is added to it. Regards, -Martin _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Andres Valloud-4
On 25 Apr 2014, at 11:35 , Andres Valloud <[hidden email]> wrote: > Guys, just look at LimitedPrecision>>isWithin:ulpsOf:. +1. Better be certain about the valid range of the numbers you’re comparing if using difference +static threshold for comparison… 10000.0 unitOfLeastPrecision 9.76562e-4 100000.0 unitOfLeastPrecision 0.0078125 1000000.0 unitOfLeastPrecision 0.0625 (For instance, if you’re not, you might end up like me, with an infinite loop in your iterative method where said comparison is the end condition) Cheers, Henry _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc signature.asc (859 bytes) Download Attachment |
See also LimitedPrecisionReal>>ulpsAwayFrom:.
On 4/28/14 2:43 , Henrik Johansen wrote: > > On 25 Apr 2014, at 11:35 , Andres Valloud <[hidden email]> wrote: > >> Guys, just look at LimitedPrecision>>isWithin:ulpsOf:. > > +1. > > Better be certain about the valid range of the numbers you’re comparing if using difference +static threshold for comparison… > 10000.0 unitOfLeastPrecision 9.76562e-4 > 100000.0 unitOfLeastPrecision 0.0078125 > 1000000.0 unitOfLeastPrecision 0.0625 > > (For instance, if you’re not, you might end up like me, with an infinite loop in your iterative method where said comparison is the end condition) > > Cheers, > Henry > vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Free forum by Nabble | Edit this page |