You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以非科学计数法打印浮点数,自动修剪末尾零(最多4位小数)

问题:如何优雅格式化double类型数据

需求明确:

  • 禁止使用科学计数法输出
  • 小数点后最多保留4位,末尾的零自动修剪;如果没有小数部分,直接去掉小数点

试过fmt库、iostream、printf的多种格式化方式,都没法精准满足需求,示例代码如下:

#include <iostream>
#include <fmt/format.h>
#include <iomanip>
int main() {
    std::cout << fmt::format("{:.4}\n", 123456789.1);                       // 结果不符合:输出科学计数法1.235e+08
    std::cout << std::setprecision(4) << 123456789.1 << "\n";               // 同上问题
    std::cout << fmt::format("{:.4f}\n", 123456789.1);                      // 结果不符合:带末尾零123456789.1000
    printf("%.4f\n", 123456789.1);                                          // 同上问题
    std::cout << std::fixed << std::setprecision(4) << 123456789.1 << "\n"; // 同上问题
}

目前是手动修剪{:.4f}输出结果的末尾零,但想找更优雅的解决方案。


优雅解决方案

1. 利用fmt库的trim_zeroes特性(推荐)

如果使用的是fmt 8.0及以上版本,可以直接用内置的trim_zeroes标志(简写!t),一步到位满足需求:

#include <fmt/format.h>
#include <iostream>

int main() {
    fmt::print("{:.4f!t}\n", 123456789.1);  // 输出:123456789.1
    fmt::print("{:.4f!t}\n", 123.4000);      // 输出:123.4
    fmt::print("{:.4f!t}\n", 123.0000);      // 输出:123
    fmt::print("{:.4f!t}\n", 123.45678);     // 输出:123.4568(自动四舍五入到4位小数)
}

这个方式完全不需要手动处理字符串,是最简洁优雅的方案。

2. 自定义格式化函数(兼容旧版fmt或C++标准库)

如果没法用高版本fmt,或者想用标准库实现,可以封装一个复用的格式化函数,先按固定4位小数输出,再自动修剪末尾零和多余的小数点:

基于fmt库的实现

#include <fmt/format.h>
#include <string>
#include <iostream>

std::string format_double(double d) {
    std::string result = fmt::format("{:.4f}", d);
    // 去掉末尾所有连续的零
    result.erase(result.find_last_not_of('0') + 1);
    // 如果最后一位是小数点,也删掉
    if (!result.empty() && result.back() == '.') {
        result.pop_back();
    }
    return result;
}

int main() {
    std::cout << format_double(123456789.1) << "\n";  // 123456789.1
    std::cout << format_double(123.4000) << "\n";      // 123.4
    std::cout << format_double(123.0000) << "\n";      // 123
    std::cout << format_double(123.45678) << "\n";     // 123.4568
}

基于C++标准库的实现(无第三方依赖)

#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>

std::string format_double(double d) {
    std::stringstream ss;
    ss << std::fixed << std::setprecision(4) << d;
    std::string result = ss.str();
    
    result.erase(result.find_last_not_of('0') + 1);
    if (!result.empty() && result.back() == '.') {
        result.pop_back();
    }
    return result;
}

int main() {
    std::cout << format_double(123456789.1) << "\n";  // 123456789.1
    std::cout << format_double(123.4000) << "\n";      // 123.4
    std::cout << format_double(123.0000) << "\n";      // 123
    std::cout << format_double(123.45678) << "\n";     // 123.4568
}

3. C++20 std::format方案

C++20引入的std::format语法和fmt库几乎一致,同样可以用自定义函数实现:

#include <format>
#include <string>
#include <iostream>

std::string format_double(double d) {
    std::string result = std::format("{:.4f}", d);
    result.erase(result.find_last_not_of('0') + 1);
    if (!result.empty() && result.back() == '.') {
        result.pop_back();
    }
    return result;
}

int main() {
    std::cout << format_double(123456789.1) << "\n";
    std::cout << format_double(123.4000) << "\n";
}

内容的提问来源于stack exchange,提问作者CygnusX1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 08:25:55