使用printf将输出精确到与输入相同的位数?

4

我希望写出一段代码,使得输出结果和输入内容一样精确。例如,如果我执行以下代码:

scanf("%f", &n);
printf("%f", n);

如果我输入 1.2,它应该输出 1.2,但实际上输出的是 1.200000。同样对于整数也是一样的,如果我输入 9,它只应该输出 9,而不是 9.00。有没有什么方法可以解决这个问题?


4
一种方法是将它们存储为字符串。在进行计算时,只需使用atof函数将其转换为数字。 - Buddhima Gamlath
@BLUEPIXY: 在某些情况下,%g 可能会选择使用 e-notation 格式。 - 0xF1
@MadHatter 我知道。但是指出了很有价值的东西。 - BLUEPIXY
@BLUEPIXY:好的!我指出这一点是因为我认为楼主可能不想以那种方式打印。无论如何,这肯定是有价值的。 :) - 0xF1
4个回答

1

OP没有说明如何处理像"9.00"这样的输入。我认为OP希望看到"9.00"打印出来,而不是像输入一样只有个位数和十分位。

首先需要将数字读取为字符串,以便稍后评估其精度。数字及其精度需要分别存储在变量中。建议使用@bgamlath提出的结构体。

使用sscanf()atof()解析字符串。
解析字符串以查找'.'的位置。

int VikasRead(float *value, int *precision) {
  char buf[100];
  *precision = 0;
  if (fgets(buf, sizeof buf, stdin) == NULL) return EOF;
  int end;
  int retval = sscanf(buf, "%f%n", value, &end);
  char * dp = strchr(buf, '.');
  if (dp != NULL && retval == 1) {
    *precision = &buf[end] - dp;
  }
  return retval;
}

int VikasWrite(float value, int precision) {
  int retval;
  if (precision > 1) {
    // Note: printf("%.*f\n", 0, value) is UB.
    retval = printf("%.*f\n", precision - 1, value);  // 1.234
  }
  else if (precision == 0) {;
    retval = printf("%.0f\n", value);  // 123
    }
  else {
    retval = printf("%#.0f\n", value); // 123.
  }
  return retval;
}

void VikasTest(void) {
  float value;
  int precision;
  while (VikasRead(&value, &precision) == 1) {
    VikasWrite(value, precision);
  }
}

指数型输入,例如1.23e56会使过程变得复杂,但方法仍然相同。需要额外查找'e''E'
一些地区使用','作为小数点,进一步增加了复杂性。

0

一种解决方案是将所有用户输入存储为它们本身。使用 char 指针和 gets()scanf("%s", ...)

如果您还想在计算中使用它们,请使用 atof 进行转换。

此外,您可以使用结构体来存储输入表示和数值。

stract Number{
 float val;
 char * representaion; // or only precision if you like.
}

0
使用格式说明符%0.7g,因为float的最大精度为7位数字。
#include <stdio.h>

int numberLenght(float d);

int main(void)
{
    float d;
    printf("input: ");
    scanf("%f", &d);
    printf("your input was: %0.7g\n", d);
    return 0;
}

对于 double 类型,请使用 %0.16gdouble 的最大精度为 16 位数字)


“float类型的最大精度为7位数字,double类型的最大精度为16位数字”这个规定是从哪里得出的呢?肯定不是C语言规范。C语言规范§5.2.4.2.2只规定了floatdouble的最小精度分别为6和10位数字,但没有规定最大精度的限制。请参考Printf width specifier to maintain precision of floating-point value - chux - Reinstate Monica

0

尝试使用宽度说明符:

printf("%.1f", n);

阅读this以获取更多详细信息。

但是,需要注意的一点是:对于floatdouble:由于精度限制,您可能无法将1.2打印为1.2000甚至1.2,它可能会变成1.1996...之类的东西。

好吧,那是完全不同的话题,在SO上已经讨论得很好了,您可以尝试在互联网或这里的SO上搜索相同的内容。

更新:
对于可变精度,您可以使用printf("%*f", <width>, <float number>);。更多详情请参见此处


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接