A double-to-string conversion algorithm based on Schubfach and yy with implementations in C and C++
- Round trip guarantee
- Shortest decimal representation
- Correct rounding
- High performance
- Fast compile time
- IEEE 754
doubleandfloatsupport - Safer API than classic
dtoa - Negative zero dependencies
- Small, clean codebase consisting of one source file and an optional header
- Permissive license
#include "zmij.h"
#include <stdio.h>
int main() {
char buf[zmij::double_buffer_size];
zmij::write(buf, sizeof(buf), 5.0507837461e-27);
puts(buf);
}More than 4x faster than Ryu used by multiple C++ standard library implementations, 9x faster than double-conversion and ~2.5x faster than Schubfach on dtoa-benchmark run on Apple M1.
| Function | Time (ns) | Speedup |
|---|---|---|
| ostringstream | 888.474 | 0.83x |
| sprintf | 734.683 | 1.00x |
| double-conversion | 86.827 | 8.46x |
| to_chars | 42.795 | 17.17x |
| ryu | 39.258 | 18.71x |
| schubfach | 25.199 | 29.15x |
| fmt | 23.718 | 30.98x |
| dragonbox | 21.602 | 34.01x |
| yy | 14.960 | 49.11x |
| xjb64 | 10.598 | 69.32x |
| zmij | 9.567 | 76.79x |
| null | 0.993 | 739.80x |
Compile time is ~135ms by default and ~155ms with optimizations enabled as measured by
% time c++ -c zmij.cc [-O2]
taking the best of 3 runs.
- C++: https://github.com/vitaut/zmij/blob/main/zmij.cc (reference implementation)
- C: https://github.com/vitaut/zmij/blob/main/zmij.c
- Rust: https://github.com/dtolnay/zmij
- Zig: https://github.com/de-sh/zmij
- 1 instead of 3 multiplications by powers of 10 in the common case
- Faster logarithm approximations
- Faster division and modulo
- Fewer conditional branches
- More efficient significand and exponent output
- Improved storage of powers of 10
Żmij (pronounced roughly zhmeey or more precisely /ʐmij/) is a Polish word that refers to a mythical dragon- or serpent-like creature. This continues the dragon theme started by Steele and White. Nice feature of this name is that it has a floating point in the first letter.