comparing floats

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

comparing floats

Adam Crumpton
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
Reply | Threaded
Open this post in threaded view
|

Re: comparing floats

Dennis smith-4

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
Reply | Threaded
Open this post in threaded view
|

Re: comparing floats

Dennis smith-4
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
Reply | Threaded
Open this post in threaded view
|

transforming floats [was: comparing floats]

Adam Crumpton
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
Reply | Threaded
Open this post in threaded view
|

Re: transforming floats [was: comparing floats]

Tom Robinson-4
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:

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


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: transforming floats [was: comparing floats]

Paul Baumann
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
Reply | Threaded
Open this post in threaded view
|

Re: transforming floats [was: comparing floats]

Andres Valloud-4
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
Reply | Threaded
Open this post in threaded view
|

Re: transforming floats [was: comparing floats]

Martin McClure-5
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
Reply | Threaded
Open this post in threaded view
|

Re: transforming floats [was: comparing floats]

Henrik Sperre Johansen
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
Reply | Threaded
Open this post in threaded view
|

Re: transforming floats [was: comparing floats]

Andres Valloud-4
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