C程序给出了意外的答案

时间:2018-08-16 01:38:22

标签: c floating-point string-formatting truncate

#include <stdio.h>

int main(){

    float a;

    scanf("%f",&a);
    a=(int)(a*1000+0.5);
    printf("%.5f\n",a);
    a=a/1000;
    printf("%.5f\n",a);

    return 0;
}

编写此程序可以以特定方式将浮点数四舍五入到小数点后3位;例如65.43296应该打印为65.43200,而不是65.432

根据逻辑它应该可以工作,但是我得到了一个意外的答案,如下所示:

1234.56789        
1234568.00000    
1234.567993

解释这种行为。

2 个答案:

答案 0 :(得分:1)

尽管输入为"1234.56789",但这只是在float a中保存的值 附近。

float作为32位对象,只能精确存储 大约2 32 个不同的值。由于float中的typical binary encoding,1234.56789不是这2 32 之一。而是使用最近的浮点数。

1234.56787109375   // nearest float's exact value
1234.56789
1234.5679931640625 // next nearest float's exact value

a*1000+0.5的结果应为1234568.375,而(int)(a*1000+0.5)的结果为1234568.0。到目前为止,还不足为奇。

a/1000;也是float,并且由于它也不是2 32 之一,因此结果是最接近的float

1234.5679931640625 // nearest float.
1234.568           // math result of 1234568.0/1000
1234.568115234375  // next nearest float
然后,OP会看到

printf("%.5f\n", 1234.5679931640625)

1234.56799

通常,float将在前导有效位数为6或更少时提供预期的答案。 OP对"1234.56800"的期望是9位数字。


使用了double的硬代码,当前导有效数字的数量超过15时,可能会发生类似的意外答案。

答案 1 :(得分:0)

对于您的问题的不一致的解释是float类型可以使用的小数位数。它的简单精度范围为3.4 E-38 to 3.4E+38(具有4个字节)。万一您应该使用double,范围为1.7 E-308 to 1.7E+308,但是会占用更多的内存(8个字节)。

#include <stdio.h>

int main(){

    double a;

    scanf("%lf",&a);
    a=(int)(a*1000+0.5);
    printf("%.5f\n",a);
    a=a/1000;
    printf("%.5lf\n",a);

    return 0;
}