我想使用数字的前五位数进行计算。 例如, 浮点数: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位用于存储尾数。有没有办法减少分配的位数?
有关如何做到这一点的任何建议?
答案 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-05
是0.00004235...
。现在,如果您将其乘以10000
,那么它将0.42365..
。现在你说我希望表达式以那种形式表示。在这种情况下,floorf
会返回float
。将它存储在一个变量中你会很高兴。舍入值将在该变量中。但是您会看到向下舍入的值为0
。这就是你得到的。
float rounded_down = floorf(num * 10000) / 10000;
这将保留.
之后向下舍入为4位的正确值(不是带有E
或e
的指数表示法)。不要将该值与用于表示它的格式说明符混淆。
为了获得所需的结果,您需要做的是将小数位移到右侧。要做到这一点,请使用更大的数字。 (1e7
或1e8
或您想要的。)
答案 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
的实际数学结果略有不同数字。此外,log10
或pow
的不良实现可能导致结果与真实的数学结果不同。
答案 3 :(得分:1)
我想使用数字的前五位进行计算。
通常,浮点数使用二进制编码,OP希望使用5个重要的十进制数字。这是有问题的,因为4.23654897E-05
和4.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
。