如何在libfmt中禁用double类型-nan值的负号输出?
如何在libfmt中去除double类型-nan值的负号?
要解决fmt库输出-nan的问题,你可以通过自定义格式化逻辑,将所有NaN(无论符号位如何)统一输出为nan,以下是两种可行方案:
方案一:全局修改double的格式化行为
通过特化fmt::formatter<double>,覆盖默认的NaN处理逻辑,全局生效:
#include <fmt/core.h> #include <cmath> #include <string> namespace fmt { template <> struct formatter<double> : formatter<std::string_view> { // 保留原有的格式解析逻辑(支持精度、格式符号等) template <typename ParseContext> constexpr auto parse(ParseContext& ctx) { return formatter<std::string_view>::parse(ctx); } template <typename FormatContext> auto format(double value, FormatContext& ctx) { if (std::isnan(value)) { // 所有NaN统一输出为"nan" return format_to(ctx.out(), "nan"); } // 其他值(包括无穷大、正常浮点数)使用默认格式化 return formatter<std::string_view>::format(fmt::format("{}", value), ctx); } }; } // namespace fmt // 测试示例 int main() { double pos_nan = std::nan(""); double neg_nan = -std::nan(""); double inf = std::numeric_limits<double>::infinity(); double neg_inf = -std::numeric_limits<double>::infinity(); fmt::print("Positive NaN: {}\n", pos_nan); // 输出 nan fmt::print("Negative NaN: {}\n", neg_nan); // 输出 nan fmt::print("Positive Inf: {}\n", inf); // 输出 inf fmt::print("Negative Inf: {}\n", neg_inf); // 输出 -inf fmt::print("Normal double: {:.2f}\n", 3.1415); // 输出 3.14 return 0; }
方案二:按需使用包装类型(非全局修改)
如果不想全局改变所有double的格式化行为,可以创建一个包装类,仅对需要处理的NaN值生效:
#include <fmt/core.h> #include <cmath> struct NormalizedDouble { double value; }; namespace fmt { template <> struct formatter<NormalizedDouble> { // 支持原有的格式参数解析 template <typename ParseContext> constexpr auto parse(ParseContext& ctx) { return ctx.begin(); } template <typename FormatContext> auto format(const NormalizedDouble& nd, FormatContext& ctx) { if (std::isnan(nd.value)) { return format_to(ctx.out(), "nan"); } return format_to(ctx.out(), "{}", nd.value); } }; } // namespace fmt // 使用示例 int main() { double neg_nan = -std::nan(""); // 仅对包装后的值处理NaN符号 fmt::print("Normalized NaN: {}\n", NormalizedDouble{neg_nan}); // 输出 nan // 普通double仍保持原有行为 fmt::print("Original NaN: {}\n", neg_nan); // 输出 -nan return 0; }
注意事项
- 两种方案都依赖
<cmath>中的std::isnan来判断NaN值,确保编译时开启C++11及以上标准。 - 如果需要同时统一无穷大的输出(比如将
-inf改为inf),可以在格式化逻辑中添加std::isinf的判断分支。
内容的提问来源于stack exchange,提问作者peepsalot
相关产品推荐
相关产品推荐

