Как вычислить максимум / минимум 8 различных значений с плавающей точкой - PullRequest
2 голосов
/ 13 января 2011

Мне нужно найти максимум и минимум 8 значений с плавающей точкой, которые я получаю.Я сделал следующим образом.Но сравнения с плавающей точкой идут не так, как предупреждает любая хорошая книга C!Как точно рассчитать максимальное и минимальное значения.

main()
{
    float mx,mx1,mx2,mx3,mx4,mn,mn1,mn2,mn3,mn4,tm1,tm2;

    mx1 = mymax(2.1,2.01); //this returns 2.09999 instead of 2.1 because a is passed as 2.09999.
    mx2 = mymax(-3.5,7.000001);
    mx3 = mymax(7,5);
    mx4 = mymax(7.0000011,0); //this returns incorrectly- 7.000001
    tm1 = mymax(mx1,mx2);
    tm2 = mymax(mx3,mx4);
    mx = mymax(tm1,tm2);

    mn1 = mymin(2.1,2.01);
    mn2 = mymin(-3.5,7.000001);
    mn3 = mymin(7,5);
    mn4 = mymin(7.0000011,0);
    tm1 = mymin(mx1,mx2);
    tm2 = mymin(mx3,mx4);
    mn = mymin(tm1,tm2);


    printf("Max is %f, Min is %f \n",mx,mn);

    getch();
}

float mymax(float a,float b)
{
    if(a >= b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

float mymin(float a,float b)
{
    if(a <= b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

Как мне выполнить точное сравнение этих чисел?Это все код С.

спасибо.

-AD.

Ответы [ 4 ]

2 голосов
/ 13 января 2011

Вы делаете точное сравнение этих чисел. Проблема (по крайней мере, с вашим примером кода) состоит в том, что float просто не имеет достаточно цифр точности, чтобы достаточно представить значения ваших литералов. 7.000001 и 7.0000011 просто настолько близко друг к другу, что мантисса 32-битного float не может представлять их по-разному.

Но пример кажется искусственным. Какую реальную проблему вы пытаетесь решить? С какими ценностями вы на самом деле будете работать? Или это просто учебное упражнение?

Лучшее решение зависит от ответа на этот вопрос. Если ваши фактические значения требуют большей точности, чем может обеспечить float, используйте double. Если вам нужно точное представление десятичных цифр, используйте библиотеку десятичных типов. Если вы хотите лучше понять, как работают значения с плавающей запятой, прочитайте Руководство с плавающей запятой .

0 голосов
/ 13 января 2011

Я бы сказал, что эти сравнения на самом деле точны, поскольку никакое значение не изменяется.

Проблема в том, что многие литералы с плавающей точкой не могут быть точно представлены числами с плавающей точкой IEEE-754. Так например 2.1.

Если вам нужно точное представление десятизначных базовых чисел, вы можете, например, написать свою собственную арифметику BCD с фиксированной точкой.

Относительно нахождения минимума и максимума одновременно:

Способ, который требует меньшего количества сравнений, заключается в том, что для каждой индексной пары (2 * i, 2 * i + 1) сначала находят минимум (n / 2 сравнения)

Затем найдите минимум минимумов ((n-1) / 2 сравнения) и максимум максимумов ((n-1) / 2 сравнения).

Таким образом, мы получаем (3 * n-2) / 2 сравнения вместо (2 * n-2) / 2 при поиске минимального и максимального разделенных значений.

0 голосов
/ 13 января 2011

Сравнение < и > всегда работает корректно с плавающими или двойными числами.Только сравнение == имеет проблемы, поэтому рекомендуется использовать epsilon.

Так что ваш метод расчета min, max не имеет проблем.Обратите внимание, что если вы используете float, вы должны использовать обозначение 2.1f вместо 2.1.Просто записка.

0 голосов
/ 13 января 2011

Вы можете сделать точное сравнение поплавков.Либо непосредственно как float, либо приведя их к int с тем же битовым представлением.

float a = 1.0f;
float b = 2.0f;
int &ia = *(int *)(&a);
int &ib = *(int *)(&b);

/* you can compare a and b, or ia and ib, the results will be the same,
   whatever the values of the floats are.
   Floats are ordered the correct way when its bits are considered as int
   and thus can be compared (provided that float and int both are 32 bits).
 */

Но вы никогда не сможете точно представить 2.1 как число с плавающей точкой.

Ваша проблема - не проблема сравнения, это проблема представления значения.

...