-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
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
[+-]InfinityandNaN. - The formatter traits are used for more than UI output.
to_stringis 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:
Debugis 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.8eformat in C and other languages, but whereas C round-trips every value, Rust round-trips every value but minus zero.Debugis for debugging. Serialization formats need to be stable and documented. We would need to documentDebug's output and guarantee its backward compatibility.Displayandto_stringare 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 toDebug. 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.