【问题标题】:C program is giving unexpected answerC 程序给出了意想不到的答案
【发布时间】:2018-08-16 01:38:21
【问题描述】:
#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

解释这种行为。

【问题讨论】:

标签: c floating-point string-formatting truncate


【解决方案1】:

虽然输入的是"1234.56789",但这只是接近保存在float a中的值。

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

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,因为它也不是这 232 之一,所以结果是最接近的 float

1234.5679931640625 // nearest float.
1234.568           // math result of 1234568.0/1000
1234.568115234375  // next nearest float

printf("%.5f\n", 1234.5679931640625) 然后被 OP 看到。

1234.56799

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


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

【讨论】:

    【解决方案2】:

    您的问题中不一致的解释是 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-20
      • 2012-10-01
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-17
      相关资源
      最近更新 更多