getfloat返回23.7999

时间:2010-01-06 23:38:21

标签: c floating-point

#define MAXBUF 1000
int buf[MAXBUF];
int buffered = 0;
int bufp = 0;

int getch()
{
    if(bufp > 0) {
       if(!--bufp)
          buffered = 0;

       return buf[bufp];
    }
    else {
       buffered = 0;
       return getchar();
    }

}

void ungetch(int c)
{
     buf[bufp++] = c;
     buffered = 1;
}

int getfloat(float *pn)
{
    int c, sign, sawsign;
    float power = 1.0;

    while(isspace(c=getch()))
         ;

    if(!isdigit(c) && c!= '+' && c!= '-' && c != '.') {
          ungetch(c);
          return 0;
    }

    sign = (c == '-') ? -1 : 1;

    if(sawsign = (c == '-' || c == '+'))
       c = getch();

    if(c != '.' && !isdigit(c)) {
         ungetch(c);

         if(sawsign)
            ungetch((sign == -1) ? '-' : '+');

         return 0;
    }

    for(*pn = 0.0; isdigit(c); c = getch())
        *pn = 10.0 * *pn + (float)(c - '0');

    if(c == '.')
       while(isdigit(c = getch())) {
         *pn = 10.0 * *pn + (float)(c - '0');
          power *= 10.0;
       }

    *pn *= sign;
    *pn /= power;

    ungetch(c);
    return c;
}

当我输入23.8时它总是返回23.7999,我不知道为什么。谁能告诉我为什么?

3 个答案:

答案 0 :(得分:5)

数字以基数2表示,基数2浮点值不能精确地表示每个基数为10的十进制值。您输入的内容23.8将转换为其最接近的等效base-2值,该值不完全是23.8。当您打印此近似值时,它将打印为23.7999

您还使用float,它是最小的浮点类型,并且只有24位精度(大约7位十进制数字)。如果切换到double,精度位数会超过float的两倍,因此十进制值(如23.8)与其double表示之间的差异要小得多。这可能允许打印例程更好地执行舍入,以便您23.8double。但是,变量中的实际值仍不完全是23.8。

作为一般建议,除非您有大量的浮点值(使内存使用成为主要考虑因素),否则最好在需要浮点类型时使用double。你没有摆脱所有奇怪的行为,但你会发现它比float更少。

答案 1 :(得分:3)

因为某些浮点数是inherently inaccurate

答案 2 :(得分:2)

鉴于IEEE 754浮标的精度有限,

23.8无法准确表示。