> On Nov 9, 2017, at 10:55 AM, Rick Mann via swift-users 
> <swift-users@swift.org> wrote:
> 
> Why is % not available for floating point numbers?


This has been discussed extensively. Swift had this this operator originally, 
but we removed it. Here’s the rationale I gave back then:

-----------

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.

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.


_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to