Skip to content

fmt::format("{}", 1e+N) compared to std::format("{}", 1e+N) #4678

@dubois

Description

@dubois

Context: I recently hit a case where an earlier version of fmt violated my assumption that a "{}" would generate no more than 15 characters for a float32. For my unlucky case, it generated 16 characters for 1e15f. I checked godbolt to see if this is fixed in a more-recent version, and it is 👍🏽. But while checking, I noticed some other differences between std::format and fmt::format. Are these differences intentional?

godbolt link

Godbolt's most-recent fmt is 11.2; "trunk" does not work for me.

fmt: 110200
f32 fmt  4 1000                  std  4 1000                
f32 fmt  5 10000                 std  5 10000               
f32 fmt  6 100000                std  5 1e+05               
f32 fmt  5 1e+15                 std  5 1e+15               
f32 fmt  5 1e+16                 std  5 1e+16               

f64 fmt  4 1000                  std  4 1000                
f64 fmt  5 10000                 std  5 10000               
f64 fmt  6 100000                std  5 1e+05               
f64 fmt 16 1000000000000000      std  5 1e+15   
f64 fmt  5 1e+16                 std  5 1e+16                   

And the older behavior I ran into, for completeness.

fmt: 100201
f32 fmt  4 1000                  std  4 1000                
f32 fmt  5 10000                 std  5 10000               
f32 fmt  6 100000                std  5 1e+05               
f32 fmt 16 1000000000000000      std  5 1e+15       <-- overflowed my 15+1-byte buffer
f32 fmt  5 1e+16                 std  5 1e+16               

f64 fmt  4 1000                  std  4 1000                
f64 fmt  5 10000                 std  5 10000               
f64 fmt  6 100000                std  5 1e+05               
f64 fmt 16 1000000000000000      std  5 1e+15               
f64 fmt  5 1e+16                 std  5 1e+16                    

Somewhat related; I studied the documentation before writing this up

The default floating-point representation in {fmt} uses the smallest precision that provides round-trip guarantees [...]
std::format ... currently tries to generate the smallest number of characters (ignoring redundant digits and sign in exponent) and may procude [sic] more decimal digits than necessary

Is this talking about examples like "1e+03" (1 decimal digit, 5 characters) vs "1000" (4 decimal digits, 4 characters)? Given the documentation, it seems like {fmt} should be using scientific notation for all these test cases?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions