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数据分析助手
小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。
像人一样思考的AI智能体
imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。
AI数字人视频创作平台
Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个 人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。
一站式AI创作平台
提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作
AI办公助手,复杂任务高效处理
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学 生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号