Как обрабатывать (устанавливать условия и сравнивать) подписанные числа с плавающей точкой в ​​C? - PullRequest
0 голосов
/ 01 марта 2019

Я пытаюсь сравнить 2 переменные с плавающей точкой.

Но сравнение не удалось из-за другого знака:

int main()
{
    //---------------------------------
    float d = 0.1;
    float f1, f2;
    printf("data: %.1f\n", d);
    //---------------------------------
    d -= 0.1; // 0.0
    f1 = d;
    printf("data: %.1f\n", d);
    printf("f1: %.1f\n", f1);
    //---------------------------------
    d -= 0.1; // -0.1
    printf("data: %.1f\n", d);
    //--------------------------------
    d += 0.1; // -0.0
    f2 = d;
    printf("data: %.1f\n", d);
    printf("f2: %.1f\n", f2);
    //---------------------------------

    if (f1 == f2)
    {
        printf("f1 and f2 equals\n");  // should get here
    }
    else
    {
        printf("f1 and f2 NOT equals\n");
    }

    if (f2 != -0.0)
    {
        printf("f2 NOT equal -0.0 \n"); // should get here
    }
    else
    {
        printf("f2 equals -0.0 \n"); 
    }
}

Вывод: вывод

  • данные: 0,1
  • данные: 0,0
  • f1: 0,0
  • данные: -0,1
  • данные: -0,0
  • f2: -0.0
  • f1 и f2 НЕ равно
  • f2 НЕ равно -0.0

Как правильно установить условия для сравнения значений -0.0 и 0.0?

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

В C 0.1 - это константа с плавающей запятой двойной точности, т.е. ее можно рассматривать как имеющую тип double.0.1 не может быть точно представлен ни float, ни double.Это похоже на то, что 1/3 не представляется точно в базе 10 с конечным числом цифр.

Преобразования, необходимые для добавления 0.1 к float, теряют точность (это отсекает часть дробицифры), что затрудняет сравнение на равенство.

У вас есть три варианта.Ваша программа будет работать так, как вы ожидаете, если вы либо

  • замените объявления float на double объявлений
  • замените каждый экземпляр 0.1 на 0.1f
  • используйте предложение Педро

Первое делает ваши переменные числами с двойной точностью, а второе делает ваши константы числами с одинарной точностью.

Однако существует более широкая проблема ссравнивая значения с плавающей запятой для равенства в этом, за исключением дробей, в которых знаменатель является степенью 2, ни одно число не может быть выражено в точности как float или double.Вам нужно сделать что-то вроде , что Педро предлагает .

0 голосов
/ 01 марта 2019

Это на самом деле ограничение точности, которое затрудняет вам здесь, каждый расчет сделан с ограниченной точностью

длинное объяснение в Википедии

Чтобы преодолеть это, выпотребуется разрешить определенные диапазоны:

if (f1 == f2)

может стать

if( ((f1 - f2) < 0.001) &&  ((f1 - f2) > -0.001) )

, если вы можете допустить заданный диапазон 0,001, в противном случае выберите в соответствии с вашими потребностями.То же самое для

if (f2 != -0.0)

, здесь вы также должны указать диапазон, потому что при некоторых вычислениях вы только иногда получаете определенное постоянное значение.Надеюсь, это поможет.

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