Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions