fast_float 库为 C++ 的 float 和 double 类型以及整数类型提供了快速的仅头文件实现的 from_chars 函数。这些函数将表示十进制值的 ASCII 字符串(如 1.3e10)转换为二进制类型。我们提供精确舍入(包括向偶数舍入)。根据我们的经验,这些 fast_float 函数比现有 C++ 标准库中的同类数字解析函数快很多倍。
具体来说,fast_float 提供了以下两个函数来解析浮点数,语法类似于 C++17(库本身只需要 C++11):
from_chars_result from_chars(const char* first, const char* last, float& value, ...); from_chars_result from_chars(const char* first, const char* last, double& value, ...);
你也可以解析整数类型:
返回类型(from_chars_result)定义为以下结构体:
struct from_chars_result { const char* ptr; std::errc ec; };
它解析字符序列 [first,last) 中的数字。它解析浮点数时期望一种与 C++17 from_chars 函数等效的与区域设置无关的格式。 结果浮点值是最接近的浮点值(使用 float 或 double),对于恰好落在两个值之间的数值,使用"向偶数舍入"约定。 也就是说,我们根据 IEEE 标准提供精确解析。
解析成功时,返回值中的指针(ptr)被设置为指向解析后的数字之后,并且引用的 value 被设置为解析后的值。如果出错,返回的 ec 包含一个代表性错误,否则存储默认值(std::errc())。
实现不会抛出异常,也不会分配内存(例如,使用 new 或 malloc)。
它可以解析无穷大和 NaN 值。
示例:
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::string input = "3.1416 xyz "; double result; auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); if(answer.ec != std::errc()) { std::cerr << "解析失败\n"; return EXIT_FAILURE; } std::cout << "解析到的数字为 " << result << std::endl; return EXIT_SUCCESS; }
你可以解析带分隔符的数字:
const std::string input = "234532.3426362,7869234.9823,324562.645"; double result; auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); if(answer.ec != std::errc()) { // 检查错误 } // 此时 result == 234532.3426362 if(answer.ptr[0] != ',') { // 意外的分隔符 } answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); if(answer.ec != std::errc()) { // 检查错误 } // 此时 result == 7869234.9823 if(answer.ptr[0] != ',') { // 意外的分隔符 } answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); if(answer.ec != std::errc()) { // 检查错误 } // 此时 result == 324562.645
与 C++17 标准一样,fast_float::from_chars 函数接受一个可选的最后参数,类型为 fast_float::chars_format。这是一个位集值:我们检查 fmt & fast_float::chars_format::fixed 和 fmt & fast_float::chars_format::scientific 是否设置,以确定我们是否允许定点和科学计数法。默认值是 fast_float::chars_format::general,它允许 fixed 和 scientific 两种格式。
该库遵循 C++17 规范(参见 20.19.3.(7.1))。
from_chars 函数不跳过前导空白字符。+ 号。float 和 double 类型)。我们寻找最接近的值。当介于两个二进制浮点数之间时,我们向偶数尾数舍入。此外,我们有以下限制:
float 和 double 类型。1e9999),我们用无穷大或负无穷大值表示,并将返回的 ec 设置为 std::errc::result_out_of_range。我们支持 Visual Studio、macOS、Linux、freeBSD。我们支持大端和小端。我们支持 32 位和 64 位系统。
我们假设舍入模式设置为最近值(std::fegetround() == FE_TONEAREST)。
你也可以使用不同的进制(例如 2、10、16)解析整数类型。以下代码将打印数字 22250738585072012 三次:
uint64_t i; const char str[] = "22250738585072012"; auto answer = fast_float::from_chars(str, str + strlen(str), i); if (answer.ec != std::errc()) { std::cerr << "解析失败\n"; return EXIT_FAILURE; } std::cout << "解析到的数字为 "<< i << std::endl; const char binstr[] = "1001111000011001110110111001001010110100111000110001100"; answer = fast_float::from_chars(binstr, binstr + strlen(binstr), i, 2); if (answer.ec != std::errc()) { std::cerr << "解析失败\n"; return EXIT_FAILURE; } std::cout << "解析到的数字为 "<< i << std::endl; const char hexstr[] = "4f0cedc95a718c"; answer = fast_float::from_chars(hexstr, hexstr + strlen(hexstr), i, 16); if (answer.ec != std::errc()) { std::cerr << "解析失败\n"; return EXIT_FAILURE; } std::cout << "解析到的数字为 "<< i << std::endl;
在 C++20 中,你可以使用 fast_float::from_chars 在编译时解析字符串,如下例所示:
// consteval 在 C++20 中强制函数进行编译时求值。 consteval double parse(std::string_view input) { double result; auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); if(answer.ec != std::errc()) { return -1.0; } return result; } // 这个函数应该编译为一个仅返回 3.1415 的函数。 constexpr double constexptest() { return parse("3.1415 input"); }
该库还支持固定宽度的浮点类型,如 std::float32_t 和 std::float64_t。例如,你可以这样写:
std::float32_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
我们还支持UTF-16和UTF-32输入,以及ASCII/UTF-8,如下例所示:
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::u16string input = u"3.1416 xyz "; double result; auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); if(answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } std::cout << "parsed the number " << result << std::endl; return EXIT_SUCCESS; }
C++标准规定 from_chars 必须与区域设置无关。特别是,小数分隔符必须是句点(.)。然而,一些用户仍然希望以区域相关的方式使用 fast_float 库。通过使用名为 from_chars_advanced 的单独函数,我们允许用户传递一个包含自定义小数分隔符(例如逗号)的 parse_options 实例。你可以像这样使用它:
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::string input = "3,1416 xyz "; double result; fast_float::parse_options options{fast_float::chars_format::general, ','}; auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } std::cout << "parsed the number " << result << std::endl; return EXIT_SUCCESS; }
你也可以解析类似Fortran的输入:
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::string input = "1d+4"; double result; fast_float::parse_options options{ fast_float::chars_format::fortran }; auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); if((answer.ec != std::errc()) || ((result != 10000))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } std::cout << "parsed the number " << result << std::endl; return EXIT_SUCCESS; }
你也可以强制使用JSON格式(RFC 8259):
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::string input = "+.1"; // 不合法 double result; fast_float::parse_options options{ fast_float::chars_format::json }; auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); if(answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; }
默认情况下,JSON格式不允许 inf:
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::string input = "inf"; // JSON中不合法 double result; fast_float::parse_options options{ fast_float::chars_format::json }; auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); if(answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; } }
你可以使用非标准的 json_or_infnan 变体来允许它:
#include "fast_float/fast_float.h" #include <iostream> int main() { const std::string input = "inf"; // JSON中不合法,但我们通过json_or_infnan允许它 double result; fast_float::parse_options options{ fast_float::chars_format::json_or_infnan }; auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); if(answer.ec != std::errc() || (!std::isinf(result))) { std::cerr << "should have parsed infinity\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; }
fast_float库是以下项目的一部分:
from_chars 函数依赖于fast_float。fastfloat算法是LLVM标准库的一部分。AdaCore有一个衍生实现。
fast_float库提供了与fast_double_parser库相似的性能,但使用了从头重新设计的更新算法,同时提供了更符合C++程序员期望的API。fast_double_parser库是Microsoft LightGBM机器学习框架的一部分。
rcppfastfloat。fast-float-rust。FastDoubleParser。它被用于重要系统,如Jackson。csFastFloat。在某些系统上,它可以以1 GB/s的速度解析随机浮点数。我们发现它通常比最好的可用竞争对手快两倍,比许多标准库实现快很多倍。
<img src="https://yellow-cdn.veclightyear.com/0a4dffa0/e9a76bcd-76fa-451e-8fd3-379bf577458e.png" width="400"> ``` $ ./build/benchmarks/benchmark # 解析范围在[0,1)的随机整数 体积 = 2.09808 MB netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s ```请访问 https://github.com/lemire/simple_fastfloat_benchmark 查看我们的基准测试代码。
本库设计为仅头文件。CMake 文件提供了 fast_float 目标,它只是指向 include 目录的指针。
如果您将 fast_float 仓库放入您的 CMake 项目中,您应该能够以这种方式使用它:
add_subdirectory(fast_float) target_link_libraries(myprogram PUBLIC fast_float)
或者,如果您有足够新的 CMake 版本(至少 3.11 或更高),您可能希望自动获取依赖项:
FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/lemire/fast_float.git GIT_TAG tags/v1.1.2 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) target_link_libraries(myprogram PUBLIC fast_float)
您应该更改 GIT_TAG 行,以获取您希望使用的版本。
如果需要,可以使用 script/amalgamate.py 脚本生成库的单一头文件版本。
只需从此仓库的根目录运行脚本即可。
如果需要,您可以按照命令行帮助中的说明自定义许可证类型和输出文件。
您可以直接下载自动生成的单一头文件:
https://github.com/fastfloat/fast_float/releases/download/v6.1.4/fast_float.h
如果您需要支持 RFC 7159(JSON 标准),您可能需要考虑使用 fast_double_parser 库。
尽管这项工作受到许多不同人的启发,但它特别受益于与 Michael Eisel 的交流,他以其关键见解激发了原始研究,以及与 Nigel Tao 的交流,他提供了宝贵的反馈。Rémy Oudompheng 首次实现了我们在长位数情况下使用的快速路径。
该库包含了改编自 Google Wuffs(由 Nigel Tao 编写)的代码,该代码最初是在 Apache 2.0 许可下发布的。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用,一键生成无水印视频


实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。


选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


最强AI数据分析助手
小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。


像人一样思考的AI智能体
imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号