0

A checker(of type double) array is obtained from a gsl_vector in the following way.

for (i=0; i<M; i++)
{               
    checker[i] = (double)gsl_vector_get(check, i);
    printf(" %f", checker[i]);
}

Array checker has [ 3.000000 -3.000000 -11.000000 -5.000000 ] elements after the above operation (from the output of the above program).

I am facing a weird problem now.

for (i=0; i<M; i++)
{
    printf("checker: %f\n", checker[i]);        
    if(checker[0] == 3.00)
    {           
        printf("Inside If: %f\n", checker[i]);          
    }
}

The above code outputs

checker: 3.000000
checker: -3.000000
checker: -11.000000
checker: -5.000000

As seen, the if loop inside for is not executed. What could be the problem?

Edit: The above problem is gone when I directly copied [ 3.000000 -3.000000 -11.000000 -5.000000 ] into the checker Array instead of the gsl_vector_get(check,i). Check value comes from dgmev function where a matrix and a vector are multiplied.

Thanks

re3el
  • 735
  • 2
  • 12
  • 28
  • 1
    I hope the dupe will address your issue, if not, please revert. Thank you. – Sourav Ghosh Aug 06 '15 at 09:11
  • Note: you also have a typo - your `if` condition is checking `checker[0]` instead of `checker[i]`. – michel-slm Aug 06 '15 at 09:12
  • @michel-slm: That wasn't a typo, I was just checking for the first element. – re3el Aug 06 '15 at 09:13
  • @SouravGhosh: Thanks. I still didn't understand as to why the same value when printed as 3.00000 isn't equal to 3.00. – re3el Aug 06 '15 at 09:14
  • 1
    @re3el Print your values with a lot of decimal (like `%.50f`) and you will see why there are not equals. – Holt Aug 06 '15 at 09:24
  • @Holt: Ya. I just saw that they aren't the same. Will adding a precision condition solve this issue? – re3el Aug 06 '15 at 09:29
  • 1
    @re3el If by « adding a precision condition », you mean comparing the absolute difference to a "threshold", yes it will. What you should do is something like `if (abs(checker[0] - 3) < 1e-6)` (and you can change `1e-6` if you want, as long as you keep a value sufficiently large to avoid floating point issues). – Holt Aug 06 '15 at 09:34

1 Answers1

2

A floating point number maybe represented in the following form:

[sign] [mantissa] * 2[exponent]

So there will be rounding or relative errors when the space is less in memory.

From wiki:

Single-precision floating-point format is a computer number format that occupies 4 bytes (32 bits) in computer memory and represents a wide dynamic range of values by using a floating point.

enter image description here

The IEEE 754 standard specifies a binary32 as having:

Sign bit: 1 bit
Exponent width: 8 bits
Significand precision: 24 bits (23 explicitly stored)

This gives from 6 to 9 significant decimal digits precision (if a decimal string with at most 6 significant decimal is converted to IEEE 754 single precision and then converted back to the same number of significant decimal, then the final string should match the original; and if an IEEE 754 single precision is converted to a decimal string with at least 9 significant decimal and then converted back to single, then the final number must match the original [4]).

Larger (more bits) floating point representations allow for greater precision.

Floating point math is not exact. Simple values like 0.1 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. A must read:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

The IEEE standard divides exceptions into 5 classes: overflow, underflow, division by zero, invalid operation and inexact. There is a separate status flag for each class of exception. The meaning of the first three exceptions is self-evident. Invalid operation covers the situations listed in TABLE D-3, and any comparison that involves a NaN.

Sadique
  • 22,572
  • 7
  • 65
  • 91