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 one header
- Permissive license
#include "zmij.h"
#include <stdio.h>
int main() {
char buf[zmij::double_buffer_size];
zmij::write(buf, sizeof(buf), 6.62607015e-34);
puts(buf);
}More than 3x faster than Ryu used by multiple C++ standard library implementations and ~2x faster than Schubfach on dtoa-benchmark run on Apple M1.
| Function | Time (ns) | Speedup |
|---|---|---|
| ostringstream | 876.371 | 1.00x |
| sprintf | 735.924 | 1.19x |
| double-conversion | 85.654 | 10.23x |
| asteria | 71.738 | 12.22x |
| to_chars | 42.857 | 20.45x |
| ryu | 37.821 | 23.17x |
| schubfach | 24.809 | 35.32x |
| fmt | 22.316 | 39.27x |
| dragonbox | 20.724 | 42.29x |
| yy | 14.095 | 62.18x |
| zmij | 10.546 | 83.10x |
| null | 0.939 | 933.48x |
Compile time is ~135ms by default and ~155ms with optimizations enabled as measured by
% time c++ -c -std=c++20 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.