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智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
字节跳动发布的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号