使用floorf减少小数位数

时间:2018-01-30 07:34:28

标签: c floating-point floor

我想使用数字的前五位数进行计算。 例如, 浮点数:4.23654897E-05

我希望使用4.2365E-05。我尝试了以下

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

float num = 4.23654897E-05;
int main(){
float rounded_down = floorf(num * 10000) / 10000;
printf("%f",rounded_down);
return 0;

}

输出为0.000000。所需输出为4.2365E-05。 简而言之,比如分配52位用于存储尾数。有没有办法减少分配的位数?

有关如何做到这一点的任何建议?

4 个答案:

答案 0 :(得分:1)

结果是预期的。乘以10000得0.423..最接近的整数是0。因此结果为0.可以使用格式说明符%f进行舍入,以将结果打印到小数点后的某些小数位。

如果您检查floorf的返回值,您会看到它返回If no errors occur, the largest integer value not greater than arg, that is ⌊arg⌋, is returned.,其中arg是传递的参数。

不使用floatf,您可以使用%e或(%E)格式说明符进行相应的打印。

printf("%.4E",num);

输出:

4.2365E-05

David的评论之后:

你做事的方式是正确的,但你乘的数字是错误的。问题是4.2365E-050.00004235...。现在,如果您将其乘以10000,那么它将0.42365..。现在你说我希望表达式以那种形式表示。在这种情况下,floorf会返回float。将它存储在一个变量中你会很高兴。舍入值将在该变量中。但是您会看到向下舍入的值为0。这就是你得到的。

float rounded_down = floorf(num * 10000) / 10000;

这将保留.之后向下舍入为4位的正确值(不是带有Ee的指数表示法)。不要将该值与用于表示它的格式说明符混淆。

为了获得所需的结果,您需要做的是将小数位移到右侧。要做到这一点,请使用更大的数字。 (1e71e8或您想要的。)

答案 1 :(得分:1)

我会去:

printf("%.6f", num);

或者您可以尝试使用snprintf()中的stdlib.h

float num = 4.23654897E-05;  char output[50];

snprintf(output, 50, "%f", num);

printf("%s", output);

答案 2 :(得分:1)

正数且在正常范围内的数字x可以向下舍入到大约五位有效数字:

double l = pow(10, floor(log10(x)) - 4);
double y = l * floor(x / l);

这对于修改浮点算法作为学习工具非常有用 。精确的数学结果通常不能完全表示,因为二进制浮点不能精确地表示大多数十进制值。此外,pow/*操作中可能会出现舍入错误,这可能导致结果与舍入x的实际数学结果略有不同数字。此外,log10pow的不良实现可能导致结果与真实的数学结果不同。

答案 3 :(得分:1)

  

我想使用数字的前五位进行计算。

通常,浮点数使用二进制编码,OP希望使用5个重要的十进制数字。这是有问题的,因为4.23654897E-054.2365E-05之类的数字不能完全表示为float/double。我们所能做的最好就是近距离接触。

floor*()方法存在以下问题:1)负数(应使用trunc())和2)x.99995附近的值,在舍入期间可能会更改位数。我强烈建议不要使用它,因为使用它的这种解决方案在很多极端情况下失败了。

*10000 * power10,round,/(10000 * power10)方法受到1)power10计算(在这种情况下为1e5)2)舍入多个3)溢出潜力中的错误。所需的power10可能不准确。当产品接近*时出现xxxxx.5错误。通常这种中间计算是使用更宽的double数学来完成的,因此极端情况很少见。使用范围有限的(some_int_type)进行舍入不正确并且是截断而不是更好的round()rint()

接近OP的目标的方法:使用%e打印到5位有效数字并转换回来。效率不高,但处理好所有情况。

int main(void) {
  float num = 4.23654897E-05f;

  //         sign   d   .   dddd   e   sign   expo + \0
  #define N (1    + 1 + 1 + 4    + 1 + 1    + 4    + 1)
  char buf[N*2];  // Use a generous buffer - I like 2x what I think is needed.

  // OP wants 5 significant digits so print 4 digits after the decimal point.
  sprintf(buf, "%.4e", num);

  float rounded = (float) atof(buf);
  printf("%.5e %s\n", rounded, buf);
}

输出

4.23650e-05 4.2365e-05

为什么5 %.5e:典型float将按预期打印最多6位有效十进制数字(研究FLT_DIG),因此打印小数点后5位数。在这种情况下,rounded完全值约为4.236500171...e-05,因为4.2365e-05不能完全代表float