goldenmean
goldenmean

Reputation: 18966

How do I compute maximum/minimum of 8 different float values

I need to find maximum and minimum of 8 float values I get. I did as follows. But float comparisons are going awry as warned by any good C book! How do I compute the max and min in a accurate way.

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;
    }
}

How can I do exact comparisons of these floats? This is all C code.

thank you.

-AD.

Upvotes: 2

Views: 780

Answers (4)

Michael Borgwardt
Michael Borgwardt

Reputation: 346310

You are doing exact comparison of these floats. The problem (with your example code at least) is that float simply does not have enough digits of precision to represent the values of your literals sufficiently. 7.000001 and 7.0000011 simply are so close together that the mantissa of a 32 bit float cannot represent them differently.

But the example seems artificial. What is the real problem you're trying to solve? What values will you actually be working with? Or is this just an academic exercise?

The best solution depends on the answer to that. If your actual values just require somewhat more more precision than float can provide, use double. If you need exact representation of decimal digits, use a decimal type library. If you want to improve your understanding of how floating point values work, read The Floating-Point Guide.

Upvotes: 2

ypnos
ypnos

Reputation: 52337

The < and > comparison always works correct with floats or doubles. Only the == comparison has problems, therefore you are advised to use epsilon.

So your method of calculating min, max has no issue. Note that if you use float, you should use the notation 2.1f instead of 2.1. Just a note.

Upvotes: 0

Nubok
Nubok

Reputation: 3671

I'd claim that these comparisons are actually exact, since no value is altered.

The problem is that many float literals can't be represented exactly by IEEE-754 floating point numbers. So for example 2.1.

If you need an exact representation of base 10 pointed numbers you could - for example - write your own fixed point BCD arithmetic.

Concerning finding min and max at the same time:

A way that needs less comparisons is for each index pair (2*i, 2*i+1) first finding the minimum (n/2 comparisons)

Then find the minimum of the minima ((n-1)/2 comparisons) and the maximum of the maxima ((n-1)/2 comparisons).

So we get (3*n-2)/2 comparisons instead of (2*n-2)/2 when finding the minimum and maximum separated.

Upvotes: 0

Didier Trosset
Didier Trosset

Reputation: 37437

You can do exact comparison of floats. Either directly as floats, or by casting them to int with the same bit representation.

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).
 */

But you will never be able to represent exactly 2.1 as a float.

Your problem is not a problem of comparison, it is a problem of representation of a value.

Upvotes: 0

Related Questions