【问题标题】:printf double with up to n decimals but not more as needed [duplicate]printf double 最多 n 位小数,但根据需要不会更多[重复]
【发布时间】:2016-11-08 06:44:00
【问题描述】:

我想将双精度的输出跟踪到小数点后 2 位或更少。考虑以下示例:

#include <stdio.h>

int main() {
    printf( "%.2f\n", 2.    );
    printf( "%.2f\n", 2.5   );
    printf( "%.2f\n", 2.25  );
    printf( "%.2f\n", 2.125 );
}

输出是

2.00
2.50
2.25
2.12

有什么方法可以打印小于 2 位小数的值,以防需要更少?我的意思是期望的输出是

2
2.5
2.25
2.12

允许使用 iomanip 回答。我专注于 C++,而不是 C,但这个例子是 c-only。

我知道,这通常是不可能的,因为双精度值不精确,但在我的示例中它们是因为所有小数部分都是 2 的幂

Live example

【问题讨论】:

  • 为什么还需要这个?
  • 如果你知道输出,你可以有单独的 setprecision 吗?但是如果你试图检查下一个值是否为 0 然后排除它,那么它是不可能的。
  • 示例被构建为最小化。请假设,该值是未知的,但我不想在最后打印无用的零
  • 不是很好,但 sprintf 会产生一个字符串,然后手动修剪它...
  • @OmidCompSCI 这是人们经常期望的。袖珍计算器从不输出尾随零

标签: c++ c printf


【解决方案1】:

如果已知绝对值介于0.006999.995 之间,则可以使用格式%.3g

#include <stdio.h>

int main() {
    printf( "%.3g\n", 2.    );
    printf( "%.3g\n", 2.5   );
    printf( "%.3g\n", 2.25  );
    printf( "%.3g\n", 2.125 );
}

输出是

2
2.5
2.25
2.12

但对于一般情况,似乎需要修剪由snprintf() 转换的字符串:

void print_double_with_at_most_2_decimal_figures(double x) {
    char buf[400];
    int i = snprintf(buf, sizeof buf, "%.2f", x);
    while (i > 0 && buf[i - 1] == '0')
        buf[--i] = '\0';
    if (i > 0 && buf[i - 1] == '.')
        buf[--i] = '\0';
    fputs(buf, stdout);
}

【讨论】:

  • 我通常也使用你的“一般”案例——虽然不是这样一个违反直觉的函数名称:P
  • @RadLexus:当然!我的名字更具体一点;-)
【解决方案2】:

modfpow 的帮助下:

#include <stdio.h>
#include <math.h>

static int dprec(double num, int digs)
{
    if (digs <= 0) return 0;

    double integral;
    // fractional part * (10 ^ digs)
    long mul = (long)(modf(num, &integral) * pow(10, digs));

    while (digs) {
        if (mul % 10 != 0) {
            break;
        }
        mul /= 10;
        digs--;
    }
    return digs;
}

int main(void)
{
    double nums[] = {2.00, 2.50, 2.25, 2.125};

    for (size_t i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
        int prec = dprec(nums[i], 2);
        printf("%.*f\n", prec, nums[i]);
    }
    return 0;
}

输出:

2
2.5
2.25
2.12

【讨论】:

  • 即使忽略 int 范围,这对于几乎所有浮点值都无法正常工作。
  • @2501,你能举一个不起作用的例子吗?
  • 从均匀分布中随机选择一个浮点数。你应该几乎总是打一个不起作用的。稍后我会发一个反例,我现在太忙了。
  • 8798.67567,那又怎样?我听不懂,当然我们可以切换到longlong long 来扩大范围。
  • OP 说他对不准确性很好,所以你的答案是正确的,但这里有一些你的方法与确切解决方案之间存在差异的例子:ideone.com/RHo1UV
【解决方案3】:

一种方法是获取2.00 的值,然后将其分配给一个变量。这应该照顾额外的 0 并给你正确的答案。

【讨论】:

  • 不,不会的!!!!
猜你喜欢
  • 1970-01-01
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 2015-08-20
  • 1970-01-01
  • 2013-02-06
相关资源
最近更新 更多