vitaut/zmij

A fast floating-point-to-string conversion library for C and C++

399

stars

1,119

commits

C

primary language

Sep 8, 2026

updated

c
cplusplus
double
dtoa
float
floating-point
ieee754
performance
Browse cluster: Floating-Point Number Serialization

README

🐉 Żmij

CI

A fast floating-point-to-string conversion library for C and C++

Features

  • Round trip guarantee
  • Shortest decimal representation similar to Python's default output
  • Correct rounding
  • Scientific, fixed, and general formatting with a given precision (like printf's %e/%f/%g)
  • Locale-independent output
  • float, double, and long double support (IEEE 754 binary32/64/128 and x87 80-bit extended)
  • High performance
  • Small binary size
  • Fast compile time
  • Optional std::to_chars-style API, several times faster than common standard library implementations
  • Safer API than classic dtoa
  • Negative zero dependencies
  • Small, clean codebase consisting of one source file and a header
  • Permissive license

Usage

#include "zmij.h"
#include <stdio.h>

int main() {
  char buf[zmij::double_buffer_size + 1];
  auto end = zmij::write(buf, sizeof(buf), 5.0507837461e-27);
  *end = '\0';
  puts(buf);
}

For a std::to_chars-style API, include zmij-to-chars.h, which provides zmij::to_chars returning a {ptr, ec} result (usable in C++14):

#include "zmij-to-chars.h"

char buf[zmij::double_buffer_size];
auto result = zmij::to_chars(buf, buf + sizeof(buf), 5.0507837461e-27);
// result.ec == std::errc() on success; result.ptr points past the output.

Performance

On an Apple M5 Max running macOS, compiled with Clang 21.0, Żmij is more than 7x faster than Ryū, used by multiple C++ standard library implementations, ~13x faster than double-conversion and ~100x faster than sprintf on dtoa-benchmark.

Conversion time (smaller is better):

Mean conversion time on Apple M5 Max

ostringstream and sprintf are left out of the charts to keep the faster methods readable.

Time vs. digit count on Apple M5 Max

On an AMD EPYC 7C13 (Milan) running Linux, compiled with GCC 13.3, Żmij is ~3.8x faster than Ryū, ~7x faster than double-conversion and ~34x faster than sprintf.

Conversion time (smaller is better):

Mean conversion time on AMD EPYC 7C13

ostringstream and sprintf are left out of the charts to keep the faster methods readable.

Time vs. digit count on AMD EPYC 7C13

Compile time

Compile time is ~135ms by default and ~180ms with optimizations enabled as measured by

% time c++ -c zmij.cc [-O2]

taking the best of 3 runs.

Languages

Name

Żmij (pronounced roughly zhmeey or more precisely /ʐmij/) is a Polish word that refers to a mythical dragon- or serpent-like creature, continuing the dragon theme started by Steele and White.

A nice bonus is that the name even contains a "floating point" in its first letter. And to quote Aras Pranckevičius, "Żmij is also literally a beast."

Acknowledgements

We would like to express our gratitude to the individuals who have made Żmij possible:

  • Victor Zverovich (@vitaut) - Original author and maintainer of Żmij.

  • Tobias Schlüter (@TobiSchluter) - Contributed significant performance and portability improvements, including SIMD/SSE support and core algorithm refinements that enhance execution speed and cross-platform compatibility.

  • Dougall Johnson (@dougallj) – Authored the NEON implementation and contributed many optimization ideas, substantially improving performance on ARM platforms.

  • Alex Guteniev (@AlexGuteniev) - Contributed multiple fixes and improvements across build systems, platform compatibility, and testing infrastructure.

  • Xiang JunBo (@xjb714) - Contributed high-performance BCD digit extraction algorithm and additional optimization ideas used across scalar and SIMD code paths. The double path uses xjb's $10^{-k-1}$ scaling to eliminate a division from the critical path.

  • David Tolnay (@dtolnay) - Created and maintains the Rust port of Żmij, expanding the algorithm's reach and adoption in the Rust ecosystem.

  • Raffaello Giulietti - Author of the Schubfach algorithm, whose work forms a foundational basis for Żmij.

  • Yaoyuan Guo (@ibireme) - Author of the yy algorithm, whose ideas influenced key optimizations used in Żmij.

  • Junekey Jeon (@jk-jeon) - Author of the Dragonbox algorithm, which informed design and benchmarking comparisons for Żmij, as well as the to_decimal API.

  • Russ Cox (@rsc) - Described the guard-bit rerounding technique used in Żmij's fixed-precision conversion.

  • Community contributors who provided feedback, issues, suggestions, and occasional commits, helping improve the robustness and performance of Żmij.

Contributors

vitaut

1,046 commits

AlexGuteniev

31 commits

TobiSchluter

23 commits

Antares0982

4 commits

vitaut/zmij

A fast floating-point-to-string conversion library for C and C++

399

stars

1,119

commits

C

primary language

Sep 8, 2026

updated

c
cplusplus
double
dtoa
float
floating-point
ieee754
performance
Browse cluster: Floating-Point Number Serialization

README

🐉 Żmij

CI

A fast floating-point-to-string conversion library for C and C++

Features

  • Round trip guarantee
  • Shortest decimal representation similar to Python's default output
  • Correct rounding
  • Scientific, fixed, and general formatting with a given precision (like printf's %e/%f/%g)
  • Locale-independent output
  • float, double, and long double support (IEEE 754 binary32/64/128 and x87 80-bit extended)
  • High performance
  • Small binary size
  • Fast compile time
  • Optional std::to_chars-style API, several times faster than common standard library implementations
  • Safer API than classic dtoa
  • Negative zero dependencies
  • Small, clean codebase consisting of one source file and a header
  • Permissive license

Usage

#include "zmij.h"
#include <stdio.h>

int main() {
  char buf[zmij::double_buffer_size + 1];
  auto end = zmij::write(buf, sizeof(buf), 5.0507837461e-27);
  *end = '\0';
  puts(buf);
}

For a std::to_chars-style API, include zmij-to-chars.h, which provides zmij::to_chars returning a {ptr, ec} result (usable in C++14):

#include "zmij-to-chars.h"

char buf[zmij::double_buffer_size];
auto result = zmij::to_chars(buf, buf + sizeof(buf), 5.0507837461e-27);
// result.ec == std::errc() on success; result.ptr points past the output.

Performance

On an Apple M5 Max running macOS, compiled with Clang 21.0, Żmij is more than 7x faster than Ryū, used by multiple C++ standard library implementations, ~13x faster than double-conversion and ~100x faster than sprintf on dtoa-benchmark.

Conversion time (smaller is better):

Mean conversion time on Apple M5 Max

ostringstream and sprintf are left out of the charts to keep the faster methods readable.

Time vs. digit count on Apple M5 Max

On an AMD EPYC 7C13 (Milan) running Linux, compiled with GCC 13.3, Żmij is ~3.8x faster than Ryū, ~7x faster than double-conversion and ~34x faster than sprintf.

Conversion time (smaller is better):

Mean conversion time on AMD EPYC 7C13

ostringstream and sprintf are left out of the charts to keep the faster methods readable.

Time vs. digit count on AMD EPYC 7C13

Compile time

Compile time is ~135ms by default and ~180ms with optimizations enabled as measured by

% time c++ -c zmij.cc [-O2]

taking the best of 3 runs.

Languages

Name

Żmij (pronounced roughly zhmeey or more precisely /ʐmij/) is a Polish word that refers to a mythical dragon- or serpent-like creature, continuing the dragon theme started by Steele and White.

A nice bonus is that the name even contains a "floating point" in its first letter. And to quote Aras Pranckevičius, "Żmij is also literally a beast."

Acknowledgements

We would like to express our gratitude to the individuals who have made Żmij possible:

  • Victor Zverovich (@vitaut) - Original author and maintainer of Żmij.

  • Tobias Schlüter (@TobiSchluter) - Contributed significant performance and portability improvements, including SIMD/SSE support and core algorithm refinements that enhance execution speed and cross-platform compatibility.

  • Dougall Johnson (@dougallj) – Authored the NEON implementation and contributed many optimization ideas, substantially improving performance on ARM platforms.

  • Alex Guteniev (@AlexGuteniev) - Contributed multiple fixes and improvements across build systems, platform compatibility, and testing infrastructure.

  • Xiang JunBo (@xjb714) - Contributed high-performance BCD digit extraction algorithm and additional optimization ideas used across scalar and SIMD code paths. The double path uses xjb's $10^{-k-1}$ scaling to eliminate a division from the critical path.

  • David Tolnay (@dtolnay) - Created and maintains the Rust port of Żmij, expanding the algorithm's reach and adoption in the Rust ecosystem.

  • Raffaello Giulietti - Author of the Schubfach algorithm, whose work forms a foundational basis for Żmij.

  • Yaoyuan Guo (@ibireme) - Author of the yy algorithm, whose ideas influenced key optimizations used in Żmij.

  • Junekey Jeon (@jk-jeon) - Author of the Dragonbox algorithm, which informed design and benchmarking comparisons for Żmij, as well as the to_decimal API.

  • Russ Cox (@rsc) - Described the guard-bit rerounding technique used in Żmij's fixed-precision conversion.

  • Community contributors who provided feedback, issues, suggestions, and occasional commits, helping improve the robustness and performance of Żmij.

Contributors

vitaut

1,046 commits

AlexGuteniev

31 commits

TobiSchluter

23 commits

Antares0982

4 commits

Languages

C

49.5%

C++

48.2%

Python

1.8%