It looks like we have a good solution.  Per Steve and David’s suggestions:

1) Make FloatingPoint == reflexive

2) Add &== to FloatingPoint for those who specifically want IEEE behavior

3) Add a warning + fixit to ‘a != a’ 

We should take this to evolution...

Thanks,
Jon

> On Nov 1, 2017, at 10:02 AM, Stephen Canon via swift-dev 
> <swift-dev@swift.org> wrote:
> 
> 
> 
>> On Nov 1, 2017, at 12:51 PM, Greg Titus via swift-dev <swift-dev@swift.org> 
>> wrote:
>> 
>>> On Nov 1, 2017, at 9:16 AM, Ben Cohen via swift-dev <swift-dev@swift.org> 
>>> wrote:
>>>> On Oct 31, 2017, at 10:11 PM, Chris Lattner via swift-dev 
>>>> <swift-dev@swift.org> wrote:
>>>> On Oct 31, 2017, at 9:07 AM, Stephen Canon via swift-dev 
>>>> <swift-dev@swift.org> wrote:
>>>>> [Replying to the thread as a whole]
>>>>> 
>>>>> There have been a bunch of suggestions for variants of `==` that either 
>>>>> trap on NaN or return `Bool?`. I think that these suggestions result from 
>>>>> people getting tunnel-vision on the idea of “make FloatingPoint equality 
>>>>> satisfy desired axioms of Equatable / Comparable”. This is misguided. Our 
>>>>> goal is (should be) to make a language usable by developers; satisfying 
>>>>> axioms is only useful in as much as they serve that goal.
>>>>> 
>>>>> Trapping or returning `Bool?` does not make it easier to write correct 
>>>>> concrete code, and it does not enable writing generic algorithms that 
>>>>> operate on Comparable or Equatable. Those are the problems to be solved.
>>>> 
>>>> +100.  Swift isn’t the first language to face the problems of floating 
>>>> point, nor is it the first to try to shoehorn it into a framework like 
>>>> Equatable.  
>>> 
>>> Java and C# do not have this problem with their generic algorithms (albeit 
>>> possibly because of limitations in their languages that Swift doesn’t 
>>> have). Swift is setting itself up as a major language with confusing and 
>>> unjustifiable behavior by comparison. That some other languages are also 
>>> bad at this doesn’t seem relevant.
>> 
>> The common (and correct!) wisdom in _any_ programming language that uses 
>> IEEE floating point is that checking equality of two floating point values 
>> is almost always a terrible idea. Usually what you want in any real world 
>> code is to check for a difference less than some epsilon value, which 
>> depends upon context. There are just too many issues with values that aren’t 
>> exactly representable, rounding errors during computations, et cetera, for 
>> perfectly normal floats even if you completely left aside equality rules for 
>> NaN.
> 
> The common wisdom is fundamentally bogus. One should *often* use a tolerance 
> for floating-point comparison, but there’s a whole host of situations in 
> which exact equality is perfectly appropriate. Of particular note for us, 
> those situations include most generic contexts based on Equatable or 
> Comparable.
> 
>       s.contains(2)
> 
> should not return `true` if `s` contains something two-ish. It should return 
> `true` if and only if `s` contains the actual value `2`.
> 
> One might want to have an additional method on sets of 
> FloatingPoint-conforming types that uses a tolerance, but contains should do 
> precisely what it says on the tin.
> 
>> I completely understand the desire in this thread to make floating point 
>> really satisfy the axioms of Equatable, but the fact is, even if you did, 
>> using a generic algorithm that depends upon equatability with floating point 
>> types is almost always just a programming error waiting to happen. It’s 
>> implicit in the representation and use of floating point values themselves, 
>> no matter what particular implementation you decide on for == or &==.
>> 
>> If you really want to make the language better for developers, provide and 
>> emphasize fixed point or infinite precision or rational types for doing 
>> various things instead, and encourage them to shun floats as much as 
>> possible. If you really need to change anything about the standard library 
>> of Swift, my preferred solution would be to continue to provide ==(lhs : 
>> Float, rhs: Float) and != but NOT declare conformance to Equatable at all so 
>> that generic algorithms involving floats would fail to compile.
> 
> Fixed point representations have their place[1], but rationals are strictly 
> worse than floating-point representations in every way except for their 
> ability to exactly represent 1/3 in toy problems and efficiency of division 
> until you saturate the size of the denominator. I am not exaggerating. They 
> waste space, they have a highly non-uniform distribution of representable 
> values, they have many redundant representations, and denominators grow 
> exponentially in almost every non-toy problem.
> 
> Floating-point is the worst approximation to the real numbers except for all 
> the others.
> 
> – Steve
> 
> [1] Unfortunately they are generally unusable for libraries due to complete 
> lack of scale invariance. This can be worked around, but doing so requires 
> more hand-holding than floating-point.
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org <mailto:swift-dev@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-dev 
> <https://lists.swift.org/mailman/listinfo/swift-dev>
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to