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
[+-]Infinity
andNaN
. - 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 documentDebug
's output and guarantee its backward compatibility.Display
andto_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 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.