Неправильный подсчет long double

Имеется вот такой код:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
long double s21_atofLong(const char *str) {
  long int length = strlen(str);
  long double returnValue = 0;
  int counterE = 0;
    int sign = 1;
    int i = 0;
                if ((str[i] == 'i' || str[i] == 'I')
         && (str[i + 1] == 'n' || str[i + 1] == 'N')
         && (str[i + 2] == 'f' || str[i + 2] == 'F')) {
          returnValue = INFINITY;
         }
                if ((str[i] == 'N' || str[i] == 'n')
         && (str[i + 1] == 'a' || str[i + 1] == 'A')
         && (str[i + 2] == 'N' || str[i + 2] == 'n')) {
          returnValue = NAN;
         }

    if (str[i] == '+' || str[i] == '-') {
      if (str[i] == '-') {
        sign = -1;
      }
      i++;
    }
    while(str[i] >= '0' && str[i] <= '9') {
      returnValue = returnValue * 10 + (str[i] - 48);
      i++;
    }
    if (str[i] == '.') {
      i++;
    }
    int pow1 = 1;
    while(str[i] >= '0' && str[i] <= '9') {
      returnValue = returnValue + (str[i] - 48.0) / (10 * pow1);
      i++;
      pow1 = pow1 * 10;
    }
    if (str[i] == 'e') {
      i++;
    }
    int signE = 1;
    if (str[i] == '+' || str[i] == '-') {
      if (str[i] == '-') {
        signE = -1;
      }
      i++;
    }
    while(str[i] >= '0' && str[i] <= '9') {
      counterE = counterE * 10 + (str[i] - 48);
      i++;
    }
    returnValue = returnValue * pow(10, signE * counterE);
  return sign * returnValue;
}

int main(int argc, char **argv) {

    long double a1 = 1, a2 = 1;

    const char str[] = "53.123";
    const char fstr[] = "%Lf";

    a1 = s21_atofLong(str);
    sscanf(str, fstr, &a2);

printf("%.25Lf %.25Lf", a1, a2);


  return 0;
}

Почему из sscanf я получаю немного другое значение, а не как в своей функции?

53.1230000000000000051625371
53.1230000000000000016930901

Ну и получается что при сравнении значений с максимальной точностью получаю, что они не равны. Как правильно будет посчитать?


Ответы (1 шт):

Автор решения: eri

Дробное число невозможно задать точно потому что размер переменной не бесконечен. На каждом шаге оно будет округляться до ближайшего двоичнозадаваемого числа. Разное количество операций приводит к разному округлению.

Сравнивать числа с фиксированной и с плавающей точкой можно только через выражения вроде abs(a-b) < 0.0000000001. Значение подбирается исходя из оценки максимальной погрешности и требованиям к точности.

Обычно это значение зависит от погрешности вводимых данных. Минимальное значение должно быть в 2 раза больше максимальной погрешности косвенных измерений.

→ Ссылка