Skip to content

-0.0 should format with a minus sign by default #1074

Closed
@rprichard

Description

@rprichard

I think negative zero should be formatted with the minus sign preserved by default.

Issue 20596

Issue #20596 restored the sign for Debug but not for Display, because "for users, negative zero makes no sense." I feel this is a poor rationale:

  • We don't know that the user is non-technical. For exponent-form, the user might very well be technical.
  • FP is inherently non-user-friendly. Printing large and small numbers accurately and concisely requires exponent form (issue #24556) which may be unfamiliar to some users. We must also print [+-]Infinity and NaN.
  • The formatter traits are used for more than UI output. to_string is Rust's canonical string representation. It is used to serialize a float for JSON. {:10} is used to serialize floats for CSV output.

The issue indicated that the CSS serializer could instead use Debug. There are problems with using Debug for FP serialization:

  • Debug is inflexible. It should be fixed per issue #24556 to use minimal sufficient precision, but searching for this representation is non-trivial. For efficiency, familiarity, or interoperability, programs might want the exponent form {:1.8e} for serialization (for f32). This format mirrors the %1.8e format in C and other languages, but whereas C round-trips every value, Rust round-trips every value but minus zero.
  • Debug is for debugging. Serialization formats need to be stable and documented. We would need to document Debug's output and guarantee its backward compatibility.
  • Display and to_string are the default conversion APIs, so if the default suppresses -0, libraries will take this as a cue that the Rust ecosystem ought to suppress -0. In other words, it is unclear that the existing JSON and CSV serializers will change to Debug. Perhaps this is the intent; it's unclear. Outside Rust, the JSON serializers I've tested for Python, Ruby, Java (gson), and Go all output minus zero.

It is surprising that {:+} prints +0, while {:+?} prints -0 for the same number. They appear to contradict.

Other languages

Hiding minus zero makes Rust inconsistent with many other languages. Languages that show it include: C, C++, Go, Haskell, Java, Lua, OCaml, Perl, Python, Racket, and Ruby. As a systems language, it makes sense to do the same thing as C/C++, but even common Unix scripting languages show the value.

Go and Perl: the default print hides minus zero, whereas Perl's printf and Go's fmt package show it. Go's print outputs floats using the simple format [+-]N.NNNNNNe[+-]NNN; it's not trying to be user-friendly or sufficiently precise.

JavaScript hides minus zero, but it has no separate integer type. If a language must choose between preserving the illusion of an integer type or representing IEEE-754 precisely, it's reasonable to choose the former. Rust, on the other hand, has FP types. Moreover, even JavaScript's choice isn't obvious—Lua lacks integer types but still prints -0.

C# hides the minus sign.

Neither JavaScript nor C# have a built-in printf-style interface, nor do they display -0 with a + sign.

cc @rkruppe @lifthrasiir @aturon @Diggsey @SimonSapin

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiRelevant to the library API team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions