<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">One of my long-term goals is for the standard library to provide (nearly) full support for all IEEE 754 required operations, which would include something similar to what you suggest. I’d like to address those bindings under a separate proposal, however, in order to keep this one simple.</div><div class=""><br class=""></div><div class="">– Steve</div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 18, 2015, at 4:19 PM, Jacob Bandes-Storch <<a href="mailto:jtbandes@gmail.com" class="">jtbandes@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Hi Steve,<div class="">I like this idea because it removes a potential "gotcha" / unexpected behavior, and it will encourage people not to do stuff like this with floating-point numbers. (Somewhat like the clang analyzer's<span class="Apple-converted-space"> </span><a href="http://clang-analyzer.llvm.org/available_checks.html#security_checkers" class="">security.FloatLoopCounter</a><span class="Apple-converted-space"> </span>tries to do.) The remainder() behavior makes sense to me.</div><div class=""><br class=""></div><div class="">However, I think it'd be nice for the standard library to continue exposing this behavior, if possible, rather than requiring the user to "import Darwin" or "import Glibc". Can these remain as methods on the built-in floating-point types, perhaps like .mod() and .remainder(), so they can be used if truly desired?</div><div class=""><br class=""></div><div class="gmail_extra"><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class="">Jacob<br class=""></div></div></div></div><br class=""><div class="gmail_quote">On Fri, Dec 18, 2015 at 1:12 PM, Stephen Canon via swift-evolution<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div style="word-wrap: break-word;" class="">Hi everybody —<br class=""><div class=""><br class=""></div><div class="">I’d like to propose removing the “%” operator for floating-point types.</div><div class=""><br class=""></div><div class=""><b class="">Rationale:</b></div><div class="">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.</div><div class=""><br class=""></div><div class="">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).</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><div class=""><span style="white-space: pre-wrap;" class="">        </span><span style="font-family: Menlo; font-size: 11px;" class="">(swift) 10.0 % 0.1</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 187, 199);" class=""> <span class="Apple-converted-space"> </span>// r0 : Double = 0.0999999999999995 // What?!</div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 187, 199);" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">[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.]</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><b class="">Proposed Approach:</b></div><div style="margin: 0px; line-height: normal;" class="">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).</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><b class="">Alternative Considered:</b></div><div style="margin: 0px; line-height: normal;" class="">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):</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><div class=""><span style="white-space: pre-wrap;" class="">        </span><span style="font-family: Menlo; font-size: 11px;" class="">(swift) remainder(1, 0.1)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 187, 199);" class=""> <span class="Apple-converted-space"> </span>// r1 : Double = -0.000000000000000055511151231257827 // Looks like normal floating-point rounding</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 187, 199);" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">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.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><b class="">Proposal:</b></div><div style="margin: 0px; line-height: normal;" class="">Remove the % operator for floating-point types in Swift 3. Add a warning in Swift 2.2 that points out the replacement fmod(a, b).</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">Thanks for your feedback,</div><div style="margin: 0px; line-height: normal;" class="">– Steve</div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=P-2BsYbBZHRBuLDBJaL4DIKDNfkkjpROowTyRAObV11qyUirbZn2Vr2z4AYpUg3RuF7jHKqyTr-2FPGW4romSaN0fM8E-2FvPX8eQ0-2Fndo5OpP09SOSI39-2FdRMFvgyzTMRw6G91f-2BTKe7QhwDUApcZC8GDnVz0ovp5-2BpL9pbBHiTtp-2FtqlHbYph-2Bc0bUW3eskm74RTQ0-2Bb-2FMyVI9j-2Fj3LBhsZgF7-2Bh3GEin88JuFLyR35l7NQ-3D" alt="" width="1" height="1" border="0" style="min-height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;" class=""></div><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></div></div></div></div></blockquote></div><br class=""></body></html>