getfloat возвращается 23.7999 - PullRequest
       1

getfloat возвращается 23.7999

2 голосов
/ 07 января 2010
#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,7999, когда я вхожу в 23,8, и я понятия не имею, почему. Кто-нибудь может сказать мне, почему?

Ответы [ 3 ]

5 голосов
/ 07 января 2010

Числа представлены в базе 2, а значения с плавающей точкой в ​​базе 2 не могут точно представлять каждое десятичное значение в базе. То, что вы вводите как 23.8, преобразуется в его ближайшее эквивалентное значение base-2, которое не совсем 23,8. Когда вы распечатываете это приблизительное значение, оно печатается как 23.7999.

Вы также используете float, который является наименьшим типом с плавающей запятой и имеет только 24 бита точности (примерно 7 десятичных цифр). Если вы переключитесь на double, количество битов точности более чем удваивается от float, поэтому разница между десятичным значением, например 23,8, и его представлением double будет намного меньше. Это может позволить процедуре печати лучше выполнить округление, чтобы вы видели 23.8 с double. Однако фактическое значение в переменной все еще не совсем 23,8.

Как общий совет, если у вас нет огромного количества значений с плавающей запятой (что делает использование памяти вашей основной задачей), лучше использовать double всякий раз, когда вам нужен тип с плавающей запятой. Вы не избавляетесь от всего странного поведения, но вы увидите его меньше, чем с float.

3 голосов
/ 07 января 2010

Поскольку некоторые числа с плавающей запятой изначально неточны .

2 голосов
/ 07 января 2010

23,8 не может быть точно представлено, учитывая ограниченную точность операций с плавающей запятой IEEE 754.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...