double-conversion carries V8's float formatting out of the JavaScript engine
Efficient binary-decimal and decimal-binary conversion routines for IEEE doubles.
At a glance
- What is it?
- double-conversion is a BSD-3-Clause C++ library of binary-decimal and decimal-binary conversion routines for IEEE doubles, extracted from the V8 JavaScript engine and refactored for reuse. It suits projects that need exact shortest-round-trip formatting in a language whose standard library does not provide it, and it is a small library with a narrow surface.
- Who is it for?
- Adopt double-conversion if you need the shortest round-trip representation of an IEEE double, or a correctly rounded string-to-double parse, in a language or runtime where your standard library does not already do it. Do not adopt it if your language ships a correctly rounded shortest representation, because duplicating a conversion routine is work with no benefit.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The origin in V8 explains the defaults, not just the code
double-conversion provides binary-decimal and decimal-binary routines for IEEE doubles. The library consists of efficient conversion routines that have been extracted from the V8 JavaScript engine, and the code has been refactored and improved so that it can be used more easily in other projects.
That lineage is the most important fact about the library, because it explains the shape of the API. The conversion semantics are the ones JavaScript has always used, which means a number printed here looks the way it would look in a browser, and a string parsed here behaves the way a JavaScript parse would. For a project that has to round-trip numbers between a JavaScript frontend and a native backend, that consistency is the entire value proposition.
It also explains the size. This is not a general purpose arbitrary precision library, and it does not try to be. It is a focused set of routines for one machine format, IEEE doubles, with the edge cases already worked out by a production engine that has to run the same code paths millions of times a second.
The documentation is unusually prominent for a library this small. The README says there is extensive documentation in double-conversion/string-to-double.h and double-conversion/double-to-string.h, and points to test/cctest/test-conversions.cc for other examples. Reading the headers rather than a separate wiki is a deliberate choice, and it means the documentation sits next to the code it describes and cannot drift from it.
The primary language of the repository is C++, the default branch is master. The license is BSD-3-Clause, with the COPYING file at the root as the authoritative text, and that permissive licence is what lets a commercial project embed it without the obligations of copyleft.
Three build systems, and the checked-in Makefile is only a wrapper
The library can be built with scons, cmake or bazel, and the README is explicit that the checked-in Makefile simply forwards to scons and provides a shortcut to run all tests. The Makefile is two targets:
all:
scons debug=1
test:
./run_testsSo make is a debug build through scons, and make test runs the run_tests script. That is a deliberately thin wrapper, and knowing that matters if you are used to a Makefile being the source of truth.
SCons is described as the easiest way to install the library, because it builds the static and shared library and is set up to install those at the correct locations:
scons installThe DESTDIR option changes the target directory, so scons DESTDIR=alternative_directory install installs into a staging root, which is what a distribution packager needs.
CMake is the option with a real caveat. You run cmake . in the root directory, and the README warns that this overwrites the existing Makefile. Use -DBUILD_SHARED_LIBS=ON to enable shared libraries, and note that this disables static libraries, because there is currently no way to build both at the same time with cmake. That is a genuine limitation rather than a stylistic choice, and it matters for anyone whose downstream build wants the static library, since the alternative is to build with scons.
To build the test executable with cmake you use -DBUILD_TESTING=ON:
cmake . -DBUILD_TESTING=ON
make
test/cctest/cctestBazel is the simplest adoption path, through the Bazel Central Registry. To build from the latest repository you run bazel build //:double-conversion, and to run the unit test you run bazel test //:cctest.
The repository supports all three: there is an SConstruct, a CMakeLists.txt, a cmake/ directory, a BUILD file, a WORKSPACE file and a MODULE.bazel, plus a double-conversion.pc.in for pkg-config and an msvc/ directory for Visual Studio.
The shortest round-trip property is what makes these routines worth extracting
The reason a project would pull this library in rather than write printf and strtod calls is a specific property: the conversion routines produce the shortest decimal string that reads back as exactly the same double.
A double has 53 bits of significand, so a large range of decimal strings round-trip to the same value. The naive approach, printing 17 significant digits, always round-trips but produces ugly output such as 0.10000000000000001 where 0.1 would do. The other naive approach, printing the shortest digits that look right, can lose the round-trip property and silently change the value.
These routines sit between those extremes. They compute the shortest representation that is guaranteed to read back identically, which is what you want when a number crosses a language boundary and gets re-parsed on the other side. A value that survives the trip is a value you can trust, and the string is also the one a human would have written.
The alternative for most projects is the language runtime. JavaScript's own Number to string is this behaviour. Python's repr has had shortest round-trip semantics for a long time. Rust's float formatting also produces shortest round-trip output.
The interesting case is a language where the standard library does not do this, or where you need to match a specific other implementation's output exactly. If you are writing a JSON parser, a database driver, or a protocol codec in C or C++, the standard library's printf and strtod will not give you shortest round-trip output, and the difference is visible in tests, in golden files, and in anything that hashes the serialised form.
One caution applies to every use of this library, including inside V8. The shortest representation is not the same as the closest representation, and the closest representation is not always the shortest. When a project needs a specific rounding behaviour rather than the shortest round-trip, that is a separate decision and the flags in the header are where it gets made.
The cctest binary is where the correctness argument lives
The test directory is the part of the repository that deserves attention, because this is a library whose correctness is the product.
The test suite is test/cctest, with test-conversions.cc given as the place to find examples of usage. The README does not describe test cases, which is a reasonable choice for a library whose test code is the documentation, but it does mean the coverage argument has to be made by reading the test directory rather than by reading a coverage percentage.
The two headers are the other half of the story. The README calls the documentation in string-to-double.h and double-to-string.h extensive, and for a library like this that is not marketing. String-to-double conversion is where the hard cases live: values just below or just above a representable range boundary, subnormals, values that are exactly halfway between two doubles, the shortest-string tie-breaking rules, and the difference between a parse that is correctly rounded and one that is merely close. Each of those is a decision that has to be documented, and each of those is a case a test has to cover.
The build systems reflect that the test binary is a first-class target. With cmake you need -DBUILD_TESTING=ON to build it and then run test/cctest/cctest directly. With bazel the test is bazel test //:cctest, so the same binary is the unit test target. With the checked-in Makefile, make test runs ./run_tests, a script rather than the binary, which suggests the script handles the build environment as well as the invocation.
For a consumer, the practical advice is to read the two headers before you wire the library in. The flags are the contract, and the contract is written down.
The repository also has a Changelog file, an AUTHORS file, and a .github/ directory. The top level carries an OpenSSF Scorecard badge in the README, and the project is registered in the Bazel Central Registry, which is the path that makes it easy to consume under Bazel without vendoring.
Editorial conclusion
Adopt double-conversion if you need the shortest round-trip representation of an IEEE double, or a correctly rounded string-to-double parse, in a language or runtime where your standard library does not already do it. Do not adopt it if your language ships a correctly rounded shortest representation, because duplicating a conversion routine is work with no benefit. Before you integrate, read double-conversion/string-to-double.h and double-conversion/double-to-string.h, which the README calls the extensive documentation, and check that the flags you pass match the rounding and formatting behaviour your callers expect, since the defaults are chosen to match JavaScript semantics rather than any general standard.
Frequently asked questions
Where does the double-conversion code come from?
The library consists of efficient conversion routines extracted from the V8 JavaScript engine. The code has been refactored and improved so it can be used more easily in other projects, and the primary language of the repository is C++.
How do I build and test double-conversion?
The library can be built with scons, cmake or bazel. The checked-in Makefile forwards to scons, so make runs a debug build and make test runs the run_tests script. With cmake you use cmake . -DBUILD_TESTING=ON followed by make and then test/cctest/cctest, and with bazel you use bazel build //:double-conversion and bazel test //:cctest.
Can cmake build both static and shared libraries?
No. The README states that -DBUILD_SHARED_LIBS=ON enables shared libraries and that this disables static libraries, because there is currently no way to build both at the same time with cmake. If you need the static library, build with scons instead.
Why would a project use this instead of the standard library?
The routines produce the shortest decimal string that reads back as exactly the same double, and the string-to-double side is correctly rounded. Standard printf and strtod do not give you that property, so a codec, a parser or a database driver in C or C++ uses this library to get round-trip-safe output.
Where is the documentation for double-conversion?
The README says there is extensive documentation in double-conversion/string-to-double.h and double-conversion/double-to-string.h, and points to test/cctest/test-conversions.cc for other examples of how the routines are used.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/google-double-conversion)Was this useful?