float & fraction equality bug

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

float & fraction equality bug

Tudor Girba-2
Hi,

I just stumbled across this bug related to the equality between fraction and float:

In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]

The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:

Fraction(Number)>>adaptToFloat: rcvr andCompare: selector 
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."

rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].

^ rcvr asTrueFraction perform: selector with: self

Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?

Cheers,
Doru


--
www.tudorgirba.com
www.feenk.com

"Problem solving should be focused on describing
the problem in a way that makes the solution obvious."





Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Martin McClure-2
On 11/09/2017 06:15 AM, Tudor Girba wrote:
Hi,

I just stumbled across this bug related to the equality between fraction and float:

In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]

The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:

Fraction(Number)>>adaptToFloat: rcvr andCompare: selector 
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."

rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].

^ rcvr asTrueFraction perform: selector with: self

Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?

I think exact comparison is the best thing to do here (even though ANSI says otherwise). And an exact comparison will answer false, because there is no float that is exactly equal to 1/10 -- it is an infinitely repeating decimal in binary.

For consistency, though, it might be better to compute x - y by converting the Float to a Fraction rather than the other way around (though this would also contravene ANSI) since Fraction is the more general format (every Float can be represented exactly as a Fraction, but the reverse is not true).

Regards,
-Martin
Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Sven Van Caekenberghe-2
In reply to this post by Tudor Girba-2
Doru,

1/10 cannot be represented as Float without loss of precision. So even though (1/10) asFloat gives you 0.1, the reverse is not possible.

Floating point is a binary (as in base 2 representation), not a decimal (base 10) representation.

Consider 

  (1/8) asFloat asTrueFraction.

which is reversible.

  x := 0.125.
  y := (1/8).
  x = y ifFalse: [ 1 / (x - y) ].

You can see that a bit in the binary representation view:


Sven

On 9 Nov 2017, at 15:15, Tudor Girba <[hidden email]> wrote:

Hi,

I just stumbled across this bug related to the equality between fraction and float:
https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo

In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]

The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:

Fraction(Number)>>adaptToFloat: rcvr andCompare: selector 
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."

rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].

^ rcvr asTrueFraction perform: selector with: self

Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?

Cheers,
Doru


--
www.tudorgirba.com
www.feenk.com

"Problem solving should be focused on describing
the problem in a way that makes the solution obvious."






Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier
In reply to this post by Tudor Girba-2
Nope, not a bug.

If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
Example; Float infinity

In your case you want to protect against (x-y) isZero, so just do that.

2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]>:
Hi,

I just stumbled across this bug related to the equality between fraction and float:

In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]

The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:

Fraction(Number)>>adaptToFloat: rcvr andCompare: selector 
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."

rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].

^ rcvr asTrueFraction perform: selector with: self

Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?

Cheers,
Doru


--
www.tudorgirba.com
www.feenk.com

"Problem solving should be focused on describing
the problem in a way that makes the solution obvious."






Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier
In reply to this post by Martin McClure-2


2017-11-09 15:34 GMT+01:00 Martin McClure <[hidden email]>:
On 11/09/2017 06:15 AM, Tudor Girba wrote:
Hi,

I just stumbled across this bug related to the equality between fraction and float:

In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]

The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:

Fraction(Number)>>adaptToFloat: rcvr andCompare: selector 
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."

rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].

^ rcvr asTrueFraction perform: selector with: self

Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?

I think exact comparison is the best thing to do here (even though ANSI says otherwise). And an exact comparison will answer false, because there is no float that is exactly equal to 1/10 -- it is an infinitely repeating decimal in binary.

For consistency, though, it might be better to compute x - y by converting the Float to a Fraction rather than the other way around (though this would also contravene ANSI) since Fraction is the more general format (every Float can be represented exactly as a Fraction, but the reverse is not true).


The POV is that Float are potentially inexact (some quantity rounded to nearest representable Float).
While Fraction are exact.

If you mix exact quantity with inexact, then the result is inexact (thus Float).
It does not hurt that this choice is CPU friendly.

Regards,
-Martin
 

Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

raffaello.giulietti
In reply to this post by Nicolas Cellier
According to IEEE 754, the base of Pharo Float, *finite* values shall
behave like old plain arithmetic.




On 2017-11-09 15:36, Nicolas Cellier wrote:

> Nope, not a bug.
>
> If you use Float, then you have to know that (x -y) isZero and (x = y)
> are two different things.
> Example; Float infinity
>
> In your case you want to protect against (x-y) isZero, so just do that.
>
> 2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]
> <mailto:[hidden email]>>:
>
>     Hi,
>
>     I just stumbled across this bug related to the equality between
>     fraction and float:
>     https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
>     <https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo>
>
>     In essence, the problem can be seen that by doing this, you get a
>     ZeroDivide:
>     x := 0.1.
>     y := (1/10).
>     x = y ifFalse: [ 1 / (x - y) ]
>
>     The issue seems to come from the Float being turned to a Fraction,
>     rather than the Fraction being turned into a Float:
>
>     Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
>     "If I am involved in comparison with a Float, convert rcvr to a
>     Fraction. This way, no bit is lost and comparison is exact."
>
>     rcvr isFinite
>     ifFalse: [
>     selector == #= ifTrue: [^false].
>     selector == #~= ifTrue: [^true].
>     rcvr isNaN ifTrue: [^ false].
>     (selector = #< or: [selector = #'<='])
>     ifTrue: [^ rcvr positive not].
>     (selector = #> or: [selector = #'>='])
>     ifTrue: [^ rcvr positive].
>     ^self error: 'unknow comparison selector'].
>
>     ^ *rcvr asTrueFraction perform: selector with: self*
>
>     Even if the comment says that the comparison is exact, to me this is
>     a bug because it seems to fail doing that. What do you think?
>
>     Cheers,
>     Doru
>
>
>     --
>     www.tudorgirba.com <http://www.tudorgirba.com>
>     www.feenk.com <http://www.feenk.com>
>
>     "Problem solving should be focused on describing
>     the problem in a way that makes the solution obvious."
>
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Tudor Girba-2
In reply to this post by Nicolas Cellier
Hi,

Thanks for the answer. The example I provided was for convenience.

I still do not understand why it is wrong to expect 0.1 = (1/10) to be true.

Doru


> On Nov 9, 2017, at 3:36 PM, Nicolas Cellier <[hidden email]> wrote:
>
> Nope, not a bug.
>
> If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
> Example; Float infinity
>
> In your case you want to protect against (x-y) isZero, so just do that.
>
> 2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]>:
> Hi,
>
> I just stumbled across this bug related to the equality between fraction and float:
> https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
>
> In essence, the problem can be seen that by doing this, you get a ZeroDivide:
> x := 0.1.
> y := (1/10).
> x = y ifFalse: [ 1 / (x - y) ]
>
> The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:
>
> Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
> "If I am involved in comparison with a Float, convert rcvr to a
> Fraction. This way, no bit is lost and comparison is exact."
>
> rcvr isFinite
> ifFalse: [
> selector == #= ifTrue: [^false].
> selector == #~= ifTrue: [^true].
> rcvr isNaN ifTrue: [^ false].
> (selector = #< or: [selector = #'<='])
> ifTrue: [^ rcvr positive not].
> (selector = #> or: [selector = #'>='])
> ifTrue: [^ rcvr positive].
> ^self error: 'unknow comparison selector'].
>
> ^ rcvr asTrueFraction perform: selector with: self
>
> Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?
>
> Cheers,
> Doru
>
>
> --
> www.tudorgirba.com
> www.feenk.com
>
> "Problem solving should be focused on describing
> the problem in a way that makes the solution obvious."
>
>
>
>
>
>

--
www.tudorgirba.com
www.feenk.com

"We are all great at making mistakes."









Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier
In reply to this post by raffaello.giulietti


2017-11-09 15:44 GMT+01:00 Raffaello Giulietti <[hidden email]>:
According to IEEE 754, the base of Pharo Float, *finite* values shall behave like old plain arithmetic.


This is out of context.
There is no such thing as Fraction type covered by IEEE 754 standard.

Anyway relying upon Float equality should allways be subject to extreme caution and examination

For example, what do you expect with plain old arithmetic in mind:

    a := 0.1.
    b := 0.3 - 0.2.
    a = b

This will lead to (a - b) reciprocal = 3.602879701896397e16
If it is in a Graphics context, I'm not sure that it's the expected scale...



On 2017-11-09 15:36, Nicolas Cellier wrote:
Nope, not a bug.

If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
Example; Float infinity

In your case you want to protect against (x-y) isZero, so just do that.

2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email] <mailto:[hidden email]>>:


    Hi,

    I just stumbled across this bug related to the equality between
    fraction and float:
    https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
    <https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo>

    In essence, the problem can be seen that by doing this, you get a
    ZeroDivide:
    x := 0.1.
    y := (1/10).
    x = y ifFalse: [ 1 / (x - y) ]

    The issue seems to come from the Float being turned to a Fraction,
    rather than the Fraction being turned into a Float:

    Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
    "If I am involved in comparison with a Float, convert rcvr to a
    Fraction. This way, no bit is lost and comparison is exact."

    rcvr isFinite
    ifFalse: [
    selector == #= ifTrue: [^false].
    selector == #~= ifTrue: [^true].
    rcvr isNaN ifTrue: [^ false].
    (selector = #< or: [selector = #'<='])
    ifTrue: [^ rcvr positive not].
    (selector = #> or: [selector = #'>='])
    ifTrue: [^ rcvr positive].
    ^self error: 'unknow comparison selector'].

    ^ *rcvr asTrueFraction perform: selector with: self*

    Even if the comment says that the comparison is exact, to me this is
    a bug because it seems to fail doing that. What do you think?

    Cheers,
    Doru


    --
    www.tudorgirba.com <http://www.tudorgirba.com>
    www.feenk.com <http://www.feenk.com>

    "Problem solving should be focused on describing
    the problem in a way that makes the solution obvious."









Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier
In reply to this post by Tudor Girba-2


2017-11-09 15:48 GMT+01:00 Tudor Girba <[hidden email]>:
Hi,

Thanks for the answer. The example I provided was for convenience.

I still do not understand why it is wrong to expect 0.1 = (1/10) to be true.

Doru


Because there are infinitely many different Fraction that would be "equal" to 0.1 then.
The first effect is that you have

a = b
a = c
b < c

You are breaking the fact that you can sort these Numbers (are they Magnitude anymore?)
You are breaking the fact that you can mix these Numbers as Dictionary keys (sometimes the dictionary would have 2 elements, sometimes 3, unpredictably).


> On Nov 9, 2017, at 3:36 PM, Nicolas Cellier <[hidden email]> wrote:
>
> Nope, not a bug.
>
> If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
> Example; Float infinity
>
> In your case you want to protect against (x-y) isZero, so just do that.
>
> 2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]>:
> Hi,
>
> I just stumbled across this bug related to the equality between fraction and float:
> https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
>
> In essence, the problem can be seen that by doing this, you get a ZeroDivide:
> x := 0.1.
> y := (1/10).
> x = y ifFalse: [ 1 / (x - y) ]
>
> The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:
>
> Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
>       "If I am involved in comparison with a Float, convert rcvr to a
>       Fraction. This way, no bit is lost and comparison is exact."
>
>       rcvr isFinite
>               ifFalse: [
>                       selector == #= ifTrue: [^false].
>                       selector == #~= ifTrue: [^true].
>                       rcvr isNaN ifTrue: [^ false].
>                       (selector = #< or: [selector = #'<='])
>                               ifTrue: [^ rcvr positive not].
>                       (selector = #> or: [selector = #'>='])
>                               ifTrue: [^ rcvr positive].
>                       ^self error: 'unknow comparison selector'].
>
>       ^ rcvr asTrueFraction perform: selector with: self
>
> Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?
>
> Cheers,
> Doru
>
>
> --
> www.tudorgirba.com
> www.feenk.com
>
> "Problem solving should be focused on describing
> the problem in a way that makes the solution obvious."
>
>
>
>
>
>

--
www.tudorgirba.com
www.feenk.com

"We are all great at making mistakes."










Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

henry
In reply to this post by Tudor Girba-2
ASN.1 encoding is a long standing encoding format and includes accepted encoding of Reals and Integers. I read this thread and decided to see what difference that ASN.1 Real encoding may report between this float and the fraction. It turns out it is the same, but not in an equality test with the fraction. That is due to conversion from Fraction to Float before encoding. Here is the results I found:

ASN1OutputStream encode: (1/10).
ASN1OutputStream encode: (0.1).
bytes := #[9 9 128 201 12 204 204 204 204 204 205]

This breaks down as in:
ASN1InputStream decodeBytes: bytes.
obj := (3602879701896397/36028797018963968)

Which equals 0.1, but does not equal (1/10).

Food for thought regarding ASN.1 encoding of Reals.

- HH


-------- Original Message --------
Subject: Re: [Pharo-dev] float & fraction equality bug
Local Time: November 9, 2017 9:48 AM
UTC Time: November 9, 2017 2:48 PM
To: Pharo Development List <[hidden email]>

Hi,

Thanks for the answer. The example I provided was for convenience.

I still do not understand why it is wrong to expect 0.1 = (1/10) to be true.

Doru

On Nov 9, 2017, at 3:36 PM, Nicolas Cellier [hidden email] wrote:
Nope, not a bug.
If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
Example; Float infinity
In your case you want to protect against (x-y) isZero, so just do that.
2017-11-09 15:15 GMT+01:00 Tudor Girba [hidden email]:
Hi,
I just stumbled across this bug related to the equality between fraction and float:
In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]
The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:
Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."
rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].
^ rcvr asTrueFraction perform: selector with: self
Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?
Cheers,
Doru
"Problem solving should be focused on describing
the problem in a way that makes the solution obvious."



"We are all great at making mistakes."









Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

henry
To break down the ASN.1 encoding of 0.1 we have the following:

sign * mantissa * (2 raisedTo: scalingFactor) * (base raisedTo: exponent).

And in this case the values for 0.1 are as follows:
self assert: sign = 1.
self assert: mantissa = 3602879701896397.
self assert: scalingFactor = 0.
self assert: base = 2.
self assert: exponent = -55.

Just to close it up...
- HH


-------- Original Message --------
Subject: Re: [Pharo-dev] float & fraction equality bug
Local Time: November 9, 2017 10:13 AM
UTC Time: November 9, 2017 3:13 PM
To: Pharo Development List <[hidden email]>

ASN.1 encoding is a long standing encoding format and includes accepted encoding of Reals and Integers. I read this thread and decided to see what difference that ASN.1 Real encoding may report between this float and the fraction. It turns out it is the same, but not in an equality test with the fraction. That is due to conversion from Fraction to Float before encoding. Here is the results I found:

ASN1OutputStream encode: (1/10).
ASN1OutputStream encode: (0.1).
bytes := #[9 9 128 201 12 204 204 204 204 204 205]

This breaks down as in:
ASN1InputStream decodeBytes: bytes.
obj := (3602879701896397/36028797018963968)

Which equals 0.1, but does not equal (1/10).

Food for thought regarding ASN.1 encoding of Reals.

- HH


-------- Original Message --------
Subject: Re: [Pharo-dev] float & fraction equality bug
Local Time: November 9, 2017 9:48 AM
UTC Time: November 9, 2017 2:48 PM
To: Pharo Development List <[hidden email]>

Hi,

Thanks for the answer. The example I provided was for convenience.

I still do not understand why it is wrong to expect 0.1 = (1/10) to be true.

Doru

On Nov 9, 2017, at 3:36 PM, Nicolas Cellier [hidden email] wrote:
Nope, not a bug.
If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
Example; Float infinity
In your case you want to protect against (x-y) isZero, so just do that.
2017-11-09 15:15 GMT+01:00 Tudor Girba [hidden email]:
Hi,
I just stumbled across this bug related to the equality between fraction and float:
In essence, the problem can be seen that by doing this, you get a ZeroDivide:
x := 0.1.
y := (1/10).
x = y ifFalse: [ 1 / (x - y) ]
The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:
Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
"If I am involved in comparison with a Float, convert rcvr to a
Fraction. This way, no bit is lost and comparison is exact."
rcvr isFinite
ifFalse: [
selector == #= ifTrue: [^false].
selector == #~= ifTrue: [^true].
rcvr isNaN ifTrue: [^ false].
(selector = #< or: [selector = #'<='])
ifTrue: [^ rcvr positive not].
(selector = #> or: [selector = #'>='])
ifTrue: [^ rcvr positive].
^self error: 'unknow comparison selector'].
^ rcvr asTrueFraction perform: selector with: self
Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?
Cheers,
Doru
"Problem solving should be focused on describing
the problem in a way that makes the solution obvious."



"We are all great at making mistakes."










Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier
In reply to this post by Nicolas Cellier
A bit like a "marronnier" (in French, a subject that is treated periodically by newspapers and magazines)

2017-11-09 15:55 GMT+01:00 Nicolas Cellier <[hidden email]>:


2017-11-09 15:48 GMT+01:00 Tudor Girba <[hidden email]>:
Hi,

Thanks for the answer. The example I provided was for convenience.

I still do not understand why it is wrong to expect 0.1 = (1/10) to be true.

Doru


Because there are infinitely many different Fraction that would be "equal" to 0.1 then.
The first effect is that you have

a = b
a = c
b < c

You are breaking the fact that you can sort these Numbers (are they Magnitude anymore?)
You are breaking the fact that you can mix these Numbers as Dictionary keys (sometimes the dictionary would have 2 elements, sometimes 3, unpredictably).


> On Nov 9, 2017, at 3:36 PM, Nicolas Cellier <[hidden email]> wrote:
>
> Nope, not a bug.
>
> If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
> Example; Float infinity
>
> In your case you want to protect against (x-y) isZero, so just do that.
>
> 2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]>:
> Hi,
>
> I just stumbled across this bug related to the equality between fraction and float:
> https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
>
> In essence, the problem can be seen that by doing this, you get a ZeroDivide:
> x := 0.1.
> y := (1/10).
> x = y ifFalse: [ 1 / (x - y) ]
>
> The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:
>
> Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
>       "If I am involved in comparison with a Float, convert rcvr to a
>       Fraction. This way, no bit is lost and comparison is exact."
>
>       rcvr isFinite
>               ifFalse: [
>                       selector == #= ifTrue: [^false].
>                       selector == #~= ifTrue: [^true].
>                       rcvr isNaN ifTrue: [^ false].
>                       (selector = #< or: [selector = #'<='])
>                               ifTrue: [^ rcvr positive not].
>                       (selector = #> or: [selector = #'>='])
>                               ifTrue: [^ rcvr positive].
>                       ^self error: 'unknow comparison selector'].
>
>       ^ rcvr asTrueFraction perform: selector with: self
>
> Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?
>
> Cheers,
> Doru
>
>
> --
> www.tudorgirba.com
> www.feenk.com
>
> "Problem solving should be focused on describing
> the problem in a way that makes the solution obvious."
>
>
>
>
>
>

--
www.tudorgirba.com
www.feenk.com

"We are all great at making mistakes."











Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

raffaello.giulietti
In reply to this post by Nicolas Cellier
On 2017-11-09 15:50, Nicolas Cellier wrote:
> This is out of context.
> There is no such thing as Fraction type covered by IEEE 754 standard.
>

Yes, I agree. But we should still strive to model arithmetic embracing
the principle of least surprise. That's why in every arithmetic system
I'm aware of (with the exception of very old CPUs dating back several
decades), for finite x, y the
     x = y if and only if x - y = 0
property holds.

Let's put it in another perspective: what's the usefulness of having
     x = y
evaluate to false just to discover that
     x - y
evaluates to 0, or the other way round?







> Anyway relying upon Float equality should allways be subject to extreme
> caution and examination
>
> For example, what do you expect with plain old arithmetic in mind:
>
>      a := 0.1.
>      b := 0.3 - 0.2.
>      a = b
>
> This will lead to (a - b) reciprocal = 3.602879701896397e16
> If it is in a Graphics context, I'm not sure that it's the expected scale...
>
>

a = b evaluates to false in this example, so no wonder (a - b) evaluates
to a big number.

But the example is not plain old arithmetic.

Here, 0.1, 0.2, 0.3 are just a shorthands to say "the Floats closest to
0.1, 0.2, 0.3" (if implemented correctly, like in Pharo as it seems).
Every user of Floats should be fully aware of the implicit loss of
precision that using Floats entails.

So, using Floats to represent decimal numbers is the real culprit in
this example, not the underlying Float arithmetic, which is very well
defined from a mathematical point of view. In other words, using Floats
to emulate decimal arithmetic will frustrate anybody because Floats work
with limited precision binary arithmetic. Users wanting to engage in
decimal arithmetic should simply not use Floats. (That's the reason for
the addition of limited precision decimal arithmetic and numbers in the
IEEE 754-2008 standard.)

That said, this does not mean we should give up useful properties like
the one discussed above. Since we *can* ensure this property, we also
should, in the spirit of the principle of least surprise.

What's problematic in Pharo is that comparison works in one way while
subtraction works in another way but, mathematically, these operations
are essentially the same. So let's be consistent.

In the case of mixed-mode Float/Fraction operations, I personally prefer
reducing the Fraction to a Float because other commercial Smalltalk
implementations do so, so there would be less pain porting code to
Pharo, perhaps attracting more Smalltalkers to Pharo.

But the main point here, I repeat myself, is to be consistent and to
have as much regularity as intrinsically possible.


Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

raffaello.giulietti
In reply to this post by Nicolas Cellier
On 2017-11-09 15:55, Nicolas Cellier wrote:

>
>
> 2017-11-09 15:48 GMT+01:00 Tudor Girba <[hidden email]
> <mailto:[hidden email]>>:
>
>     Hi,
>
>     Thanks for the answer. The example I provided was for convenience.
>
>     I still do not understand why it is wrong to expect 0.1 = (1/10) to
>     be true.
>
>     Doru
>
>
> Because there are infinitely many different Fraction that would be
> "equal" to 0.1 then.
> The first effect is that you have
>
> a = b
> a = c
> b < c
>
> You are breaking the fact that you can sort these Numbers (are they
> Magnitude anymore?)
> You are breaking the fact that you can mix these Numbers as Dictionary
> keys (sometimes the dictionary would have 2 elements, sometimes 3,
> unpredictably).
>
>

Fractions are not reliable keys anyway:
(Fraction numerator: 1 denominator: 3) = (Fraction numerator: 2
denominator: 6)
evaluates to true while
(Fraction numerator: 1 denominator: 3) hash = (Fraction numerator: 2
denominator: 6) hash
evaluates to false


Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier


2017-11-09 18:11 GMT+01:00 Raffaello Giulietti <[hidden email]>:
On 2017-11-09 15:55, Nicolas Cellier wrote:


2017-11-09 15:48 GMT+01:00 Tudor Girba <[hidden email] <mailto:[hidden email]>>:

    Hi,

    Thanks for the answer. The example I provided was for convenience.

    I still do not understand why it is wrong to expect 0.1 = (1/10) to
    be true.

    Doru


Because there are infinitely many different Fraction that would be "equal" to 0.1 then.
The first effect is that you have

a = b
a = c
b < c

You are breaking the fact that you can sort these Numbers (are they Magnitude anymore?)
You are breaking the fact that you can mix these Numbers as Dictionary keys (sometimes the dictionary would have 2 elements, sometimes 3, unpredictably).



Fractions are not reliable keys anyway:
(Fraction numerator: 1 denominator: 3) = (Fraction numerator: 2 denominator: 6)
evaluates to true while
(Fraction numerator: 1 denominator: 3) hash = (Fraction numerator: 2 denominator: 6) hash
evaluates to false


You are violating the invariants described in class comment in this case, and thus missusing Fraction.
So it's not anymore the problem of the library

Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Nicolas Cellier
In reply to this post by raffaello.giulietti


2017-11-09 18:02 GMT+01:00 Raffaello Giulietti <[hidden email]>:
On 2017-11-09 15:50, Nicolas Cellier wrote:
This is out of context.
There is no such thing as Fraction type covered by IEEE 754 standard.


Yes, I agree. But we should still strive to model arithmetic embracing the principle of least surprise. That's why in every arithmetic system I'm aware of (with the exception of very old CPUs dating back several decades), for finite x, y the
    x = y if and only if x - y = 0
property holds.

Let's put it in another perspective: what's the usefulness of having
    x = y
evaluate to false just to discover that
    x - y
evaluates to 0, or the other way round?







Anyway relying upon Float equality should allways be subject to extreme caution and examination

For example, what do you expect with plain old arithmetic in mind:

     a := 0.1.
     b := 0.3 - 0.2.
     a = b

This will lead to (a - b) reciprocal = 3.602879701896397e16
If it is in a Graphics context, I'm not sure that it's the expected scale...



a = b evaluates to false in this example, so no wonder (a - b) evaluates to a big number.


Writing a = b with floating point is rarely a good idea, so asking about the context which could justify such approach makes sense IMO.

But the example is not plain old arithmetic.

Here, 0.1, 0.2, 0.3 are just a shorthands to say "the Floats closest to 0.1, 0.2, 0.3" (if implemented correctly, like in Pharo as it seems). Every user of Floats should be fully aware of the implicit loss of precision that using Floats entails.


Yes, it makes perfect sense!
But precisely because you are aware that 0.1e0 is "the Float closest to 0.1" and not exactly 1/10, you should then not be surprised that they are not equal.

 
So, using Floats to represent decimal numbers is the real culprit in this example, not the underlying Float arithmetic, which is very well defined from a mathematical point of view. In other words, using Floats to emulate decimal arithmetic will frustrate anybody because Floats work with limited precision binary arithmetic. Users wanting to engage in decimal arithmetic should simply not use Floats. (That's the reason for the addition of limited precision decimal arithmetic and numbers in the IEEE 754-2008 standard.)

That said, this does not mean we should give up useful properties like the one discussed above. Since we *can* ensure this property, we also should, in the spirit of the principle of least surprise.

What's problematic in Pharo is that comparison works in one way while subtraction works in another way but, mathematically, these operations are essentially the same. So let's be consistent.

 
I agree that following assertion hold:
    self assert: a ~= b & a isFloat & b isFloat & a isFinite & b isFinite ==> (a - b) isZero not

But (1/10) is not a Float and there is no Float that can represent it exactly, so you can simply not apply the rules of FloatingPoint on it.

When you write (1/10) - 0.1, you implicitely perform (1/10) asFloat - 0.1.
It is the rounding operation asFloat that made the operation inexact, so it's no more surprising than other floating point common sense


In the case of mixed-mode Float/Fraction operations, I personally prefer reducing the Fraction to a Float because other commercial Smalltalk implementations do so, so there would be less pain porting code to Pharo, perhaps attracting more Smalltalkers to Pharo.

Mixed arithmetic is problematic, and from my experience mostly happens in graphics in Smalltalk.

If ever I would change something according to this principle (but I'm not convinced it's necessary, it might lead to other strange side effects),
maybe it would be how mixed arithmetic is performed...
Something like exact difference like Martin suggested, then converting to nearest Float because result is inexact:
    ((1/10) - 0.1 asFraction) asFloat

This way, you would have a less surprising result in most cases.
But i could craft a fraction such that the difference underflows, and the assertion a ~= b ==> (a - b) isZero not would still not hold.
Is it really worth it?
Will it be adopted in other dialects?

 
But the main point here, I repeat myself, is to be consistent and to have as much regularity as intrinsically possible.



I think we have as much as possible already.
Non equality resolve more surprising behavior than it creates.
It makes the implementation more mathematically consistent (understand preserving more properties).
Tell me how you are going to sort these 3 numbers:

{1.0 . 1<<60+1/(1<<60).  1<<61+1/(1<<61)} sort.

tell me the expectation of:

{1.0 . 1<<60+1/(1<<60). 1<<61+1/(1<<61)} asSet size.

tell me why = is not a relation of equivalence anymore (not associative)


Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Andres Valloud-4
In reply to this post by Tudor Girba-2
Because by definition, a floating point value is of the form

+/- 2^e * m

for some 0 <= m < M, and e in some range of values (some positive, some
negative).  There are other special cases that don't matter here, such
as NaN, INF, denormals, etc.

So now set up the equality you want.  Since it's positive we can skip
the sign.  Hence,

2^e * m = 1/10

Or, rather,

10 * 2^e * m = 1

The Fundamental Theorem of Arithmetic shows this is impossible.

Andres.

On 11/9/17 6:48 , Tudor Girba wrote:

> Hi,
>
> Thanks for the answer. The example I provided was for convenience.
>
> I still do not understand why it is wrong to expect 0.1 = (1/10) to be true.
>
> Doru
>
>
>> On Nov 9, 2017, at 3:36 PM, Nicolas Cellier <[hidden email]> wrote:
>>
>> Nope, not a bug.
>>
>> If you use Float, then you have to know that (x -y) isZero and (x = y) are two different things.
>> Example; Float infinity
>>
>> In your case you want to protect against (x-y) isZero, so just do that.
>>
>> 2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]>:
>> Hi,
>>
>> I just stumbled across this bug related to the equality between fraction and float:
>> https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
>>
>> In essence, the problem can be seen that by doing this, you get a ZeroDivide:
>> x := 0.1.
>> y := (1/10).
>> x = y ifFalse: [ 1 / (x - y) ]
>>
>> The issue seems to come from the Float being turned to a Fraction, rather than the Fraction being turned into a Float:
>>
>> Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
>> "If I am involved in comparison with a Float, convert rcvr to a
>> Fraction. This way, no bit is lost and comparison is exact."
>>
>> rcvr isFinite
>> ifFalse: [
>> selector == #= ifTrue: [^false].
>> selector == #~= ifTrue: [^true].
>> rcvr isNaN ifTrue: [^ false].
>> (selector = #< or: [selector = #'<='])
>> ifTrue: [^ rcvr positive not].
>> (selector = #> or: [selector = #'>='])
>> ifTrue: [^ rcvr positive].
>> ^self error: 'unknow comparison selector'].
>>
>> ^ rcvr asTrueFraction perform: selector with: self
>>
>> Even if the comment says that the comparison is exact, to me this is a bug because it seems to fail doing that. What do you think?
>>
>> Cheers,
>> Doru
>>
>>
>> --
>> www.tudorgirba.com
>> www.feenk.com
>>
>> "Problem solving should be focused on describing
>> the problem in a way that makes the solution obvious."
>>
>>
>>
>>
>>
>>
>
> --
> www.tudorgirba.com
> www.feenk.com
>
> "We are all great at making mistakes."
>
>
>
>
>
>
>
>
>
> .
>

Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

raffaello.giulietti
In reply to this post by Nicolas Cellier
On 2017-11-09 19:04, Nicolas Cellier wrote:

>
>
> 2017-11-09 18:02 GMT+01:00 Raffaello Giulietti
> <[hidden email] <mailto:[hidden email]>>:
>
>
>
>
>         Anyway relying upon Float equality should allways be subject to
>         extreme caution and examination
>
>         For example, what do you expect with plain old arithmetic in mind:
>
>               a := 0.1.
>               b := 0.3 - 0.2.
>               a = b
>
>         This will lead to (a - b) reciprocal = 3.602879701896397e16
>         If it is in a Graphics context, I'm not sure that it's the
>         expected scale...
>
>
>
>     a = b evaluates to false in this example, so no wonder (a - b)
>     evaluates to a big number.
>
>
> Writing a = b with floating point is rarely a good idea, so asking about
> the context which could justify such approach makes sense IMO.
>

Simple contexts, like the one which is the subject of this trail, are
the one we should strive at because they are the ones most likely used
in day-to-day working. Having useful properties and regularity for
simple cases might perhaps cover 99% of the everyday usages (just a
dishonestly biased estimate ;-) )

Complex contexts, with heavy arithmetic, are best dealt by numericists
when Floats are involved, or with unlimited precision numbers like
Fractions by other programmers.





>     But the example is not plain old arithmetic.
>
>     Here, 0.1, 0.2, 0.3 are just a shorthands to say "the Floats closest
>     to 0.1, 0.2, 0.3" (if implemented correctly, like in Pharo as it
>     seems). Every user of Floats should be fully aware of the implicit
>     loss of precision that using Floats entails.
>
>
> Yes, it makes perfect sense!
> But precisely because you are aware that 0.1e0 is "the Float closest to
> 0.1" and not exactly 1/10, you should then not be surprised that they
> are not equal.
>

Indeed, I'm not surprised. But then
     0.1 - (1/10)
shall not evaluate to 0. If it evaluates to 0, then the numbers shall
compare as being equal.

The surprise lies in the inconsistency between the comparison and the
subtraction, not in the isolated operations.



>
> I agree that following assertion hold:
>      self assert: a ~= b & a isFloat & b isFloat & a isFinite & b
> isFinite ==> (a - b) isZero not
>

The arrow ==> is bidirectional even for finite Floats:

self assert: (a - b) isZero not & a isFloat & b isFloat & a isFinite & b
isFinite ==> a ~= b




> But (1/10) is not a Float and there is no Float that can represent it
> exactly, so you can simply not apply the rules of FloatingPoint on it.
>
> When you write (1/10) - 0.1, you implicitely perform (1/10) asFloat - 0.1.
> It is the rounding operation asFloat that made the operation inexact, so
> it's no more surprising than other floating point common sense

See above my observation about what I consider surprising.




>
>
>     In the case of mixed-mode Float/Fraction operations, I personally
>     prefer reducing the Fraction to a Float because other commercial
>     Smalltalk implementations do so, so there would be less pain porting
>     code to Pharo, perhaps attracting more Smalltalkers to Pharo.
>
> Mixed arithmetic is problematic, and from my experience mostly happens
> in graphics in Smalltalk.
>
> If ever I would change something according to this principle (but I'm
> not convinced it's necessary, it might lead to other strange side effects),
> maybe it would be how mixed arithmetic is performed...
> Something like exact difference like Martin suggested, then converting
> to nearest Float because result is inexact:
>      ((1/10) - 0.1 asFraction) asFloat
>
> This way, you would have a less surprising result in most cases.
> But i could craft a fraction such that the difference underflows, and
> the assertion a ~= b ==> (a - b) isZero not would still not hold.
> Is it really worth it?
> Will it be adopted in other dialects?
>
>

As an alternative, the Float>>asFraction method could return the
Fraction with the smallest denominator that would convert to the
receiver by the Fraction>>asFloat method.

So, 0.1 asFraction would return 1/10 rather than the beefy Fraction it
currently returns. To return the beast, one would have to intentionally
invoke asExactFraction or something similar.

This might cause less surprising behavior. But I have to think more.





>     But the main point here, I repeat myself, is to be consistent and to
>     have as much regularity as intrinsically possible.
>
>
>
> I think we have as much as possible already.
> Non equality resolve more surprising behavior than it creates.
> It makes the implementation more mathematically consistent (understand
> preserving more properties).
> Tell me how you are going to sort these 3 numbers:
>
> {1.0 . 1<<60+1/(1<<60).  1<<61+1/(1<<61)} sort.
>
> tell me the expectation of:
>
> {1.0 . 1<<60+1/(1<<60). 1<<61+1/(1<<61)} asSet size.
>

A clearly stated rule, consistently applied and known to everybody, helps.

In presence of heterogeneous numbers, the rule should state the common
denominator, so to say. Hence, the numbers involved in mixed-mode
arithmetic are either all converted to one representation or all to the
other: whether they are compared or added, subtracted or divided, etc.
One rule for mixed-mode conversions, not two.




> tell me why = is not a relation of equivalence anymore (not associative)
>
>

Ensuring that equality is an equivalence is always a problem when the
entities involved are of different nature, like here. This is not a new
problem and not inherent in numbers. (Logicians and set theorists would
have much to tell.) Even comparing Points and ColoredPoints is
problematic, so I have no final answer.

In Smalltalk, furthermore, implementing equality makes it necessary to
(publicly) expose much more internal details about an object than in
other environments.





Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Stephane Ducasse-3
In reply to this post by Nicolas Cellier
There is nice little Chapter about Float based on previous discussions
with Nicolas :)
In deep into pharo.

Stef

On Thu, Nov 9, 2017 at 3:50 PM, Nicolas Cellier
<[hidden email]> wrote:

>
>
> 2017-11-09 15:44 GMT+01:00 Raffaello Giulietti
> <[hidden email]>:
>>
>> According to IEEE 754, the base of Pharo Float, *finite* values shall
>> behave like old plain arithmetic.
>>
>>
> This is out of context.
> There is no such thing as Fraction type covered by IEEE 754 standard.
>
> Anyway relying upon Float equality should allways be subject to extreme
> caution and examination
>
> For example, what do you expect with plain old arithmetic in mind:
>
>     a := 0.1.
>     b := 0.3 - 0.2.
>     a = b
>
> This will lead to (a - b) reciprocal = 3.602879701896397e16
> If it is in a Graphics context, I'm not sure that it's the expected scale...
>
>>
>>
>> On 2017-11-09 15:36, Nicolas Cellier wrote:
>>>
>>> Nope, not a bug.
>>>
>>> If you use Float, then you have to know that (x -y) isZero and (x = y)
>>> are two different things.
>>> Example; Float infinity
>>>
>>> In your case you want to protect against (x-y) isZero, so just do that.
>>>
>>> 2017-11-09 15:15 GMT+01:00 Tudor Girba <[hidden email]
>>> <mailto:[hidden email]>>:
>>>
>>>
>>>     Hi,
>>>
>>>     I just stumbled across this bug related to the equality between
>>>     fraction and float:
>>>
>>> https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo
>>>
>>> <https://pharo.fogbugz.com/f/cases/20488/x-y-iff-x-y-0-is-not-preserved-in-Pharo>
>>>
>>>     In essence, the problem can be seen that by doing this, you get a
>>>     ZeroDivide:
>>>     x := 0.1.
>>>     y := (1/10).
>>>     x = y ifFalse: [ 1 / (x - y) ]
>>>
>>>     The issue seems to come from the Float being turned to a Fraction,
>>>     rather than the Fraction being turned into a Float:
>>>
>>>     Fraction(Number)>>adaptToFloat: rcvr andCompare: selector
>>>     "If I am involved in comparison with a Float, convert rcvr to a
>>>     Fraction. This way, no bit is lost and comparison is exact."
>>>
>>>     rcvr isFinite
>>>     ifFalse: [
>>>     selector == #= ifTrue: [^false].
>>>     selector == #~= ifTrue: [^true].
>>>     rcvr isNaN ifTrue: [^ false].
>>>     (selector = #< or: [selector = #'<='])
>>>     ifTrue: [^ rcvr positive not].
>>>     (selector = #> or: [selector = #'>='])
>>>     ifTrue: [^ rcvr positive].
>>>     ^self error: 'unknow comparison selector'].
>>>
>>>     ^ *rcvr asTrueFraction perform: selector with: self*
>>>
>>>     Even if the comment says that the comparison is exact, to me this is
>>>     a bug because it seems to fail doing that. What do you think?
>>>
>>>     Cheers,
>>>     Doru
>>>
>>>
>>>     --
>>>     www.tudorgirba.com <http://www.tudorgirba.com>
>>>     www.feenk.com <http://www.feenk.com>
>>>
>>>     "Problem solving should be focused on describing
>>>     the problem in a way that makes the solution obvious."
>>>
>>>
>>>
>>>
>>>
>>>
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: float & fraction equality bug

Stephane Ducasse-3
In reply to this post by Nicolas Cellier
On Thu, Nov 9, 2017 at 5:34 PM, Nicolas Cellier
<[hidden email]> wrote:
> Note that this started a long time ago and comes up episodically
> http://forum.world.st/Fraction-equality-and-Float-infinity-problem-td48323.html
> http://forum.world.st/BUG-Equality-should-be-transitive-tc1404335.html
> https://lists.gforge.inria.fr/pipermail/pharo-project/2009-July/010496.html
>
> A bit like a "marronnier" (in French, a subject that is treated periodically
> by newspapers and magazines)

Hi nicolas except that now we could a chapter describing some of the answers :)

123