Hi Erica, thanks for the feedback.
> On Apr 14, 2016, at 6:29 PM, Erica Sadun <[email protected]> wrote:
>
> * I do use % for floating point but not as much as I first thought before I
> started searching through my code after reading your e-mail. But when I do
> use it, it's nice to have a really familiar symbol rather than a big word.
> What were the ways that it was used incorrectly? Do you have some examples?
As it happens, I have a rationale sitting around from an earlier (internal)
discussion:
While C and C++ do not provide the “%” operator for floating-point types, many
newer languages do (Java, C#, and Python, to name just a few). Superficially
this seems reasonable, but there are severe gotchas when % is applied to
floating-point data, and the results are often extremely surprising to unwary
users. C and C++ omitted this operator for good reason. Even if you think you
want this operator, it is probably doing the wrong thing in subtle ways that
will cause trouble for you in the future.
The % operator on integer types satisfies the division algorithm axiom: If b is
non-zero and q = a/b, r = a%b, then a = q*b + r. This property does not hold
for floating-point types, because a/b does not produce an integral value. If
it did produce an integral value, it would need to be a bignum type of some
sort (the integral part of DBL_MAX / DBL_MIN, for example, has over 2000 bits
or 600 decimal digits).
Even if a bignum type were returned, or if we ignore the loss of the division
algorithm axiom, % would still be deeply flawed. Whereas people are generally
used to modest rounding errors in floating-point arithmetic, because % is not
continuous small errors are frequently enormously magnified with catastrophic
results:
(swift) 10.0 % 0.1
// r0 : Double = 0.0999999999999995 // What?!
[Explanation: 0.1 cannot be exactly represented in binary floating point; the
actual value of “0.1” is
0.1000000000000000055511151231257827021181583404541015625. Other than that
rounding, the entire computation is exact.]
Proposed Approach:
Remove the “%” operator for floating-point types. The operation is still be
available via the C standard library fmod( ) function (which should be mapped
to a Swiftier name, but that’s a separate proposal).
Alternative Considered:
Instead of binding “%” to fmod( ), it could be bound to remainder( ), which
implements the IEEE 754 remainder operation; this is just like fmod( ), except
instead of returning the remainder under truncating division, it returns the
remainder of round-to-nearest division, meaning that if a and b are positive,
remainder(a,b) is in the range [-b/2, b/2] rather than [0, b). This still has
a large discontinuity, but the discontinuity is moved away from zero, which
makes it much less troublesome (that’s why IEEE 754 standardized this
operation):
(swift) remainder(1, 0.1)
// r1 : Double = -0.000000000000000055511151231257827 // Looks like normal
floating-point rounding
The downside to this alternative is that now % behaves totally differently for
integer and floating-point data, and of course the division algorithm still
doesn’t hold.
> * I don't quite get how equatable is going to work. Do you mind explaining
> that in more detail?
I’m not totally sure what your question is. Are you asking how FloatingPoint
will conform to Equatable, or how the Equatable protocol will work?
– Steve_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution