[swift-evolution] Implicit truncation

Xiaodi Wu xiaodi.wu at gmail.com
Mon May 22 15:16:32 CDT 2017

On Mon, May 22, 2017 at 10:39 Haravikk <swift-evolution at haravikk.me> wrote:

> On 22 May 2017, at 15:51, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> If we're to speak of intuition for new developers who've never used a
> programming language, who are falling back to what they know about
> mathematics, then quite literally a decimal point _is_ about division by
> ten.
> I don't think this necessarily follows; the issue here is that the
> constructor isn't explicit enough that it is simply lopping off the
> fractional part. My own experience of maths as taught in school, to go from
> a decimal to an integer I would expect to round,

You would also expect that 3 / 4 in integer math gives you 1. With integer
division, however, 3 / 4 == 0. By definition the decimal point separates an
integer from a fractional part, so the behaviors are inextricably linked.
To test this out in practice, I asked the first person with no programming
experience I just encountered today.

I said: "Let me teach you one fact about integers in a programming
language. When two integers are divided, the integer result has the
fractional part discarded; for example, 3/4 computes to 0. What would you
expect to be the result of converting 0.75 to an integer?"

He answered immediately: "I would have expected that 3/4 gives you 1, but
since 3/4 gives you 0, I'd expect 0.75 to convert to 0."

so I think it's reasonable that Swift should be clear. While it is
> reflected in the documentation, a good choice of label would allow it to be
> explicit at the point of use, without requiring a look up each time there
> is uncertainty.
> func init(truncating:Float) { … }
> Again, this particular naming suggestion has been discussed as part of the
> review of integer protocols and not adopted. The rationale was that the
> term "truncating" is intended to be left for bit patterns only. The term in
> Swift is exclusively "rounded toward zero."
> As I understand it truncation is a term of art from C at least (rounding
> toward zero is the trunc function I believe?), it also makes sense given
> that what's happening is that the fractional part is being discarded,
> regardless of how how high it may be. init(roundTowardZero:Float) seems
> like it would be very unwieldy by comparison just because truncating is
> arbitrarily reserved for bit operations.
> Also, when it comes down to it, discarding the fractional part of a float
> *is* a bit-pattern operation of a sort,

Discarding the fractional part of a floating point value is a bit pattern
operation only in the sense that any operation on any data is a bit pattern
operation. It is clearly not, however, an operation truncating a bit

as the conversion is simplistically taking the significand, dropping it
> into an Int then shifting by the exponent.

That's not correct. If you shift the significand or the significand bit
pattern of pi by its exponent, you don't get 3.

> func init(rounding:Float, _ strategy: FloatingPointRoundingRule) { … }
> Again, here, as an addition to the API, this fails the six criteria of Ben
> Cohen, as it is strictly duplicative of `T(value.rounded(strategy))`.
> Maybe, but init(rounding:) is explicit that something is being done to the
> value, at which point there's no obvious harm in clarifying what (or
> allowing full freedom). While avoiding redundancy is good as a general
> rule, it doesn't mean there can't be any at all if there's some benefit to
> it; in this case clarity of exactly what kind of rounding is taking place
> to the Float/Double value.

The bar for adding new API to the standard library is *far* higher than
"some benefit"; `Int(value.rounded(.up))` is the approved spelling for
which you are proposing a second spelling that does the same thing.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170522/29341baa/attachment.html>

More information about the swift-evolution mailing list