【问题标题】:Output a floating point value with a constant number of characters in C++在 C++ 中输出具有恒定字符数的浮点值
【发布时间】:2012-03-19 04:38:21
【问题描述】:

我在做我认为应该是 C++ 中相当简单的任务时遇到了麻烦。我正在尝试输出要写入日志文件的浮点值。日志文件有 7 个字符指定用于数字输出,但我发现在不同大小、符号和精度的广泛值(例如:1,- 0.60937、0.60937、0.009371、-0.009371)。我有一种有点老套的方法来做到这一点:

int desiredPrecision = 6;
if (runningAvg < 0)
  desiredPrecision--;
if (std::abs((long) runningAvg) < 1)
  desiredPrecision--;
else
  theFile << std::showpoint;

theFile.precision (desiredPrecision);

theFile.fill('0');
theFile.setf(std::ios_base::left, std::ios_base::adjustfield);
theFile.width(7);
theFile << runningAvg << std::endl;

但这种方式对我来说似乎非常hacky。它适用于以下数字: -0.60937(输出:-0.6094)

-1.7 (-1.7000)

-1 (-1.0000)

0.6937 (0.60937)

0.00937 (0.00937)

但它打破了 0.009371 (0.009371)

和

-0.009371 (-0.009371)

现在,我可以添加另一个级别的 if-else 语句来处理小数值,但这似乎只是增加了 hackiness 的级别,而不是一种干净的方法。我玩过 fprintf,但它似乎更关心精确的数学定义,而在这个应用程序中,我更关心始终将字段的宽度限制为 7 个字符。 (我也可以依靠这些数字永远不会太大,以至于我会溢出 6 个字符加上一个符号)

我在这里遗漏了一些明显的东西吗?任何人有任何技巧来实现这一目标吗?

【问题讨论】:

  • 你期望 -99999 的输出是什么?

标签: c++ formatting floating-point


【解决方案1】:

不知道如何使用 iostream 的东西来做到这一点,但我认为您正在寻找的 ?printf 格式字符串是其中之一:

  • %.4f 用于负数,%07.5f 用于正数。
  • %+.4f(正数前导+)
  • % .4f(正数将有一个前导空格)

【讨论】:

    【解决方案2】:

    最简单的方法是打印成一个字符串并将该字符串截断。
    您实际上是在进行文本处理/报告生成而不是浮点数处理所以将其视为格式问题

    【讨论】:

    • 正确舍入绝对不是字符串操作任务。
    • +1,虽然我同意@BenVoigt,但鉴于这将进入日志文件,这是一种可能性,不值得 -1。
    • 我玩过这个,看起来这可能是最简单的方法。我设置了一个简单的 do-while 循环以输出到 c++ std::string,如果字符串长度超过 7,则将精度减 1(通过循环最多 # 次以处理溢出)。 @BenVoigt - 我在理论上同意,但正如我所说,我正在寻找一个对数字有固定宽度要求的日志文件,在这个应用程序中我不关心数学上的严格性(阅读正确的 sigfigs)舍入/精度。谢谢!
    • @bencpeters - 正确的舍入不是,但是格式化一个数字以适应 20 个字符。
    【解决方案3】:

    如果您不关心精度(或担心对所有数字使用相同的精度),您可以对所有数字使用相同的"%7.0e" 格式。

    Example

    #include <stdio.h>
    
    static const char* format = "%7.0e";
    
    int main() {
      double a[] = {1, -0.60937, 0.60937, 0.009371, -0.009371,
                   -1, -1.2e8, 1e-4, 1e-5, -1.5e-321, 0/.0, 1/0.};
      for (unsigned i = 0; i < sizeof(a) / sizeof(*a); ++i) {
        printf(format, a[i]);
        puts("");
        if (snprintf(0,0, format, a[i]) != 7)
          return 1;
      }
    }
    

    输出

      1e+00
     -6e-01
      6e-01
      9e-03
     -9e-03
     -1e+00
     -1e+08
      1e-04
      1e-05
    -2e-321
        nan
        inf
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多