{"id":16572708,"url":"https://github.com/lemire/fast_double_parser","last_synced_at":"2025-05-15T07:05:41.295Z","repository":{"id":39992238,"uuid":"246143534","full_name":"lemire/fast_double_parser","owner":"lemire","description":"Fast function to parse strings into double (binary64) floating-point values, enforces the RFC 7159 (JSON standard) grammar: 4x faster than strtod","archived":false,"fork":false,"pushed_at":"2024-10-31T15:14:09.000Z","size":853,"stargazers_count":656,"open_issues_count":2,"forks_count":58,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-04-14T12:58:34.220Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lemire.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-09T21:14:11.000Z","updated_at":"2025-03-26T19:07:26.000Z","dependencies_parsed_at":"2024-06-19T11:29:51.284Z","dependency_job_id":"cb33584e-87f0-421d-bac1-9af8dcee6903","html_url":"https://github.com/lemire/fast_double_parser","commit_stats":{"total_commits":175,"total_committers":24,"mean_commits":7.291666666666667,"dds":"0.25142857142857145","last_synced_commit":"bc93aee338615e46faac4140dd60eef761ba5b12"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffast_double_parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffast_double_parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffast_double_parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffast_double_parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lemire","download_url":"https://codeload.github.com/lemire/fast_double_parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254292041,"owners_count":22046426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T21:28:20.323Z","updated_at":"2025-05-15T07:05:36.249Z","avatar_url":"https://github.com/lemire.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fast_double_parser: 4x faster than strtod\n![MSYS2-CI](https://github.com/lemire/fast_double_parser/workflows/MSYS2-CI/badge.svg)[![Ubuntu 22.04](https://github.com/lemire/fast_double_parser/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/lemire/fast_double_parser/actions/workflows/ubuntu.yml)\n\nUnless you need support for [RFC 7159](https://tools.ietf.org/html/rfc7159) (JSON standard), we encourage users to adopt [fast_float](https://github.com/fastfloat/fast_float) library instead. It has more functionality.\n\n\nFast function to parse ASCII strings containing decimal numbers into double-precision (binary64) floating-point values.  That is, given the string \"1.0e10\", it should return a 64-bit floating-point value equal to 10000000000. We do not sacrifice accuracy. The function will match exactly (down the smallest bit) the result of a standard function like `strtod`.\n\nWe support all major compilers: Visual Studio, GNU GCC, LLVM Clang. We require C++11.\n\nThe core of this library was ported to Go by Nigel Tao and is now a standard float-parsing routine in Go (`strconv.ParseFloat`). \n\n\n## Reference\n\n- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience 51 (8), 2021.\n\n\n\n## Usage\n\nYou should be able to just drop  the header file into your project, it is a header-only library.\n\n\nThe current API is simple enough:\n\n```C++\n#include \"fast_double_parser.h\" // the file is in the include directory\n\n\ndouble x;\nchar * string = ...\nconst char * endptr = fast_double_parser::parse_number(string, \u0026x);\n```\n\nYou must check the value returned (`endptr`): if it is `nullptr`, then the function refused to parse the input.\nOtherwise, we return a pointer (`const char *`) to the end of the parsed string. The provided\npointer (`string`) should point at the beginning of the number: if you must skip whitespace characters,\nit is your responsibility to do so.\n\n\nWe expect string numbers to follow [RFC 7159](https://tools.ietf.org/html/rfc7159) (JSON standard). In particular,\nthe parser will reject overly large values that would not fit in binary64. It will not accept\nNaN or infinite values.\n\nIt works much like the C standard function `strtod` expect that the parsing is locale-independent. E.g., it will parse 0.5 as 1/2, but it will not parse 0,5 as\n1/2 even if you are under a French system. Locale independence is by design (it is not a limitation). Like the standard C functions, it expects that the string\nrepresentation of your number ends with a non-number character (e.g., a null character, a space, a colon, etc.). If you wish the specify the end point of the string, as is common in C++, please consider the [fast_float](https://github.com/lemire/fast_float) C++ library instead.\n\n\nWe assume that the rounding mode is set to nearest, the default setting (`std::fegetround() == FE_TONEAREST`). It is uncommon to have a different setting.\n\n## What if I prefer another API?\n\nThe [fast_float](https://github.com/lemire/fast_float) offers an API resembling that of the C++17 `std::from_chars` functions. In particular, you can specify the beginning and the end of the string.\nFurthermore [fast_float](https://github.com/lemire/fast_float) supports both 32-bit and 64-bit floating-point numbers. The  [fast_float](https://github.com/lemire/fast_float) library is part of Apache Arrow, GCC 12, Safari/WebKit and other important systems.\n\n## Why should I expect this function to be faster?\n\nParsing strings into binary numbers (IEEE 754) is surprisingly difficult. Parsing a single number can take hundreds of instructions and CPU cycles, if not thousands. It is relatively easy to parse numbers faster if you sacrifice accuracy (e.g., tolerate 1 ULP errors), but we are interested in \"perfect\" parsing.\n\nInstead of trying to solve the general problem, we cover what we believe are the most common scenarios, providing really fast parsing. We fall back on the standard library for the difficult cases. We believe that, in this manner, we achieve the best performance on some of the most important cases.\n\nWe have benchmarked our parser on a collection of strings from a sample geojson file (canada.json). Here are some of our results:\n\n\n| parser                                | MB/s |\n| ------------------------------------- | ---- |\n| fast_double_parser                    | 660 MB/s  |\n| abseil, from_chars                    | 330 MB/s |\n| double_conversion                     | 250 MB/s |\n| strtod                    | 70 MB/s |\n\n(configuration: Apple clang version 11.0.0, I7-7700K)\n\nWe expect string numbers to follow [RFC 7159](https://tools.ietf.org/html/rfc7159). In particular,\nthe parser will reject overly large values that would not fit in binary64. It will not produce\nNaN or infinite values. It will refuse to parse `001` or `0.` as these are invalid number strings as\nper the [JSON specification](https://tools.ietf.org/html/rfc7159). Users who prefer a more\nlenient C++ parser may consider the [fast_float](https://github.com/lemire/fast_float) C++ library.\n\nThe parsing is locale-independent. E.g., it will parse 0.5 as 1/2, but it will not parse 0,5 as\n1/2 even if you are under a French system.\n\n\n## Requirements\n\n\nIf you want to run our benchmarks, you should have\n\n- Windows, Linux or macOS; presumably other systems can be supported as well\n- A recent C++ compiler\n- A recent cmake (cmake 3.11 or better) is necessary for the benchmarks\n\nThis code falls back on your platform's `strdtod_l` /`_strtod_l` implementation for numbers with a long decimal mantissa (more than 19 digits).\n\n## Usage (benchmarks)\n\n```\ngit clone https://github.com/lemire/fast_double_parser.git\ncd fast_double_parser\nmkdir build\ncd build\ncmake .. -DFAST_DOUBLE_BENCHMARKS=ON\ncmake --build . --config Release  \nctest .\n./benchmark\n```\nUnder Windows, the last line should be `./Release/benchmark.exe`.\n\nBe mindful that the benchmarks include the abseil library which is not supported everywhere.\n\n## Sample results\n\n\n```\n$ ./benchmark\nparsing random integers in the range [0,1)\n\n\n=== trial 1 ===\nfast_double_parser  460.64 MB/s\nstrtod         186.90 MB/s\nabslfromch     168.61 MB/s\nabsl           140.62 MB/s\ndouble-conv    206.15 MB/s\n\n\n=== trial 2 ===\nfast_double_parser  449.76 MB/s\nstrtod         174.59 MB/s\nabslfromch     152.68 MB/s\nabsl           157.52 MB/s\ndouble-conv    193.97 MB/s\n\n\n```\n\n```\n$ ./benchmark benchmarks/data/canada.txt\nread 111126 lines\n\n\n=== trial 1 ===\nfast_double_parser  662.01 MB/s\nstrtod         69.73 MB/s\nabslfromch     341.74 MB/s\nabsl           325.23 MB/s\ndouble-conv    249.68 MB/s\n\n\n=== trial 2 ===\nfast_double_parser  611.56 MB/s\nstrtod         69.53 MB/s\nabslfromch     330.00 MB/s\nabsl           328.45 MB/s\ndouble-conv    243.90 MB/s\n```\n\n\n## Ports and users\n\n- The algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). \n- This library has been ported to Go and integrated in the Go standard library.\n- It is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM).\n- It is part of the database engine [noisepage](https://github.com/cmu-db/noisepage).\n- The library has been reimplemented in [Google wuffs](https://github.com/google/wuffs/).\n- [There is a Julia port](https://github.com/JuliaData/Parsers.jl).\n- [There is a Rust port](https://github.com/ezrosent/frawk/tree/master/src/runtime/float_parse).\n- [There is a Java port](https://github.com/wrandelshofer/FastDoubleParser).\n- [There is a C# port](https://github.com/CarlVerret/csFastFloat).\n- [Bazel Central Registry](https://registry.bazel.build/modules/fast_double_parser).\n\n## Credit\n\nContributions are invited.\n\nThis is based on an original idea by Michael Eisel (joint work).\n\n## License\n\nYou may use this code under either the Apache License 2.0 or\nthe Boost Software License 1.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemire%2Ffast_double_parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flemire%2Ffast_double_parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemire%2Ffast_double_parser/lists"}