2014-07-12 2:26 GMT+02:00 Andres Valloud <[email protected]>
:

> In short, my point is that if one is going to "optimize" using floating
> point, then be thorough.  If everything is a float, then conversion isn't a
> problem, comparison isn't a problem, etc.  Starting from a more consistent
> place makes painful contortions unnecessary.
>
>
>
If the conclusion is that mixed arithmetic comparisons makes sense finally,
and that we should better avoid having the unordered {1/2<0.5. 1/2=0.5.
1/2>0.5} -> #(false false false), that's already a point.

The "painful contortions" is adressing another problem: that of
transitivity as a principle of least astonishment.
You say starting from a more consistent place, but how consistent are = and
<= among Numbers without transitivity?
If we can maintain the invariant with a pair of double dispatching methods
and coordinated hash, why shouldn't we?
Why lispers did it? (Scheme too)

For me it's like saying: "since float are inexact, we have a license to
waste ulp".
We have not. IEEE 754 model insists on operations to be exactly rounded.
These are painful contortions too, but most useful!
Extending the contortion to exact comparison sounds a natural extension to
me, the main difference is that we do not round true or false to the
nearest float, so it's even nicer!



> On 7/11/14 17:19 , Nicolas Cellier wrote:
>
>>
>>
>>
>> 2014-07-12 1:29 GMT+02:00 Andres Valloud
>> <[email protected]
>> <mailto:[email protected]>>:
>>
>>
>>              I don't think it makes sense to compare floating point
>>         numbers to
>>              other types of numbers with #=... there's a world of
>>         approximations
>>              and other factors hiding behind #=, and the occasional true
>>         answer
>>              confuses more than it helps.  On top of that, then you get
>>         x = y =>
>>              x hash = y hash, and so the hash of floating point values
>>         "has" to
>>              be synchronized with integers, fractions, scaled decimals,
>>         etc...
>>              _what a mess_...
>>
>>
>>         Yes, that's true, hash gets more complex.
>>         But then, this has been discussed before:
>>
>>         {1/2 < 0.5. 1/2 = 0.5. 1/2 > 0.5} - > #(false false false).
>>
>>         IOW, they are unordered.
>>         Are we ready to lose ordering of numbers?
>>         Practically, this would have big impacts on code base.
>>
>>
>>     IME, that's because loose code appears to work.  What enables that
>>     loose code to work is the loose mixed mode arithmetic.  I could
>>     understand integers and fractions.  Adding floating point to the mix
>>     stops making as much sense to me.
>>
>>     Equality between floating point numbers does make sense.  Equality
>>     between floating point numbers and scaled decimals or fractions...
>>     in general, I don't see how they could make sense.  I'd rather see
>>     the scaled decimals and fractions explicitly converted to floating
>>     point numbers, following a well defined procedure, and then
>> compared...
>>
>>     Andres.
>>
>>
>> Why do such mixed arithmetic comparisons make sense?
>> Maybe we used floating points in some low level Graphics for
>> optimization reasons.
>> After these optimized operations we get a Float result by contagion, but
>> our intention is still to handle Numbers.
>> It would be possible to riddle the code with explicit asFloat/asFraction
>> conversions, but that does not feel like a superior solution...
>>
>> OK, we can as well convert to inexact first before comparing for this
>> purpose.
>> That's what C does, because C is too low level to ever care of
>> transitivity and equivalence relationship.
>> It's not even safe in C because the compiler can decide to promote to a
>> larger precision behind your back...
>> But let's ignore this "feature" and see what lispers recommend instead:
>>
>> http://www.lispworks.com/documentation/lcl50/aug/aug-170.html
>>
>> It says:
>>
>> In general, when an operation involves both a rational and a
>> floating-point argument, the rational number is first converted to
>> floating-point format, and then the operation is performed. This
>> conversion process is called /floating-point contagion/
>> <http://www.lispworks.com/reference/lcl50/aug/aug-193.html#MARKER-9-47>.
>>
>> However, for numerical equality comparisons, the arguments are compared
>> using rational arithmetic to ensure transitivity of the equality (or
>> inequality) relation.
>>
>> So my POV is not very new, it's an old thing.
>> It's also a well defined procedure, and somehow better to my taste
>> because it preserve more mathematical properties.
>> If Smalltalk wants to be a better Lisp, maybe it should not constantly
>> ignore Lisp wisdom ;)
>>
>> We can of course argue about the utility of transitivity...
>> As a general library we provide tools like Dictionary that rely on
>> transitivity.
>> You can't tell how those Dictionary will be used in real applications,
>> so my rule of thumb is the principle of least astonishment.
>> I've got bitten once by such transitivity while memoizing... I switched
>> to a better strategy with double indirection as workaround: class ->
>> value -> result, but it was surprising.
>>
>>
>>         I'm pretty sure a Squeak/Pharo image wouldn't survive that long
>>         to such
>>         a change
>>         (well I tried it, the Pharo3.0 image survives, but Graphics are
>>         badly
>>         broken as I expected).
>>
>>         That's allways what made me favour casual equality to universal
>>         inequality.
>>
>>         Also should 0.1 = 0.1 ? In case those two floats have been
>>         produced by
>>         different path, different approximations they might not be
>> equal...
>>         (| a b | a := 0.1. b := 1.0e-20. a+b=a.)
>>         I also prefer casual equality there too.
>>         Those two mathematical expressions a+b and a are different but
>> both
>>         floating point expressions share same floating point
>> approximation,
>>         that's all what really counts because in the end, we cannot
>>         distinguish
>>         an exact from an inexact Float, nor two inexact Float.
>>         We lost the history...
>>
>>         Also, the inexact flag is not attached to a Float, it's only the
>>         result
>>         of an operation.
>>         Statistically, it would waste one bit for nothing, most floats
>>         are the
>>         result of an inexact operation.
>>         But who knows, both might be the result of exact operations too ;)
>>
>>
>>
>>              On 7/11/14 10:46 , stepharo wrote:
>>
>>                  I suggest you to read the Small number chapter of the
>>         Deep into
>>                  Pharo.
>>
>>                  Stef
>>
>>                  On 11/7/14 15:53, Natalia Tymchuk wrote:
>>
>>                      Hello.
>>                        I found interesting thing:
>>                      Why it is like this?
>>
>>                      Best regards,
>>                      Natalia
>>
>>
>>
>>
>>
>>
>>
>

Reply via email to