Dropping from float to double produces different results - the same code, the same compiler, the same OS

Edit: See end of question for updated answer.

I spent several weeks tracking a very strange bug in the software part I support. In short, there is an old piece of software that is in distribution and new software that must match the old. These two theories (in theory) rely on a common library [1]. However, I cannot duplicate the results generated by the original version of the library, even if the source for the two versions of the library is the same. The real code is very simple. The original version looked like this ("voodoo" commented this is not mine): [2]

// float rstr[101] declared and initialized elsewhere as a global

void my_function() {
    // I have elided several declarations not used until later in the function
    double tt, p1, p2, t2;
    char *ptr;

    ptr = NULL;
    p2 = 0.0;
    t2 = 0.0; /* voooooodoooooooooo */

    tt = (double) rstr[20];
    p1 = (double) rstr[8];

    // The code goes on and does lots of other things ...
}

, , - . , rstr[8] 101325., double [3] , p1 101324.65625. , tt 373.149999999996. , ( ). , .

( ), ( tt) . , p1 101325.0, rstr[8]. , , , p1.

, :

#include "the_header.h"

float rstr[101];
int main() {
    rstr[8] = 101325.;
    rstr[20] = 373.15;

    my_function();
}

, VC6.

4550:   tt = (double) rstr[20];
0042973F   fld         dword ptr [rstr+50h (006390a8)]
00429745   fstp        qword ptr [ebp-0Ch]
4551:   p1 = (double) rstr[8];
00429748   fld         dword ptr [rstr+20h (00639078)]
0042974E   fstp        qword ptr [ebp-14h]

, VC6 ( , VC6 ):

60:       tt = (double) rstr[20];
00408BC8   fld         dword ptr [_rstr+50h (0045bc88)]
00408BCE   fstp        qword ptr [ebp-0Ch]
61:       p1 = (double) rstr[8];
00408BD1   fld         dword ptr [_rstr+20h (0045bc58)]
00408BD7   fstp        qword ptr [ebp-14h]

, , , , _ rstr . , VC6 , . , , , , -.

, ( ) , Win32 MFC, - , MFC. , C.

.


: , , , / , , , , , , . - .

- , , , , - , , , , , , rstr[8], , double , , .

, , , . , rstr[8] GUI ( ), , . , 101325.0, , , 1.01325e5.

. Eric Postpischil unwind , . .


  • "" , . #include, , extern. , , .
  • , , . , . /* voooooodoooooooooo */, ... ... . , Fortran - . .
  • , , , .
+4
4

:

rstr[8] 101325., , double[3] , p1 101324.65625

, float 101325.0, double . () , float, ( ) , . float , , .

+6

:

  • , rstr[8] 101324.65625 p1, 101325.
  • , p1 101324.65625 .
  • ( double) .

1, rstr[8] . :

  • 20
  • , rstr[8], 64- IEEE-754
  • , .

, , , 101324.65625 rstr[8] ( ) , .

2, p1 . , p1 rstr[8].

, , , 3. :

  • , , , .
  • .
  • , .
+4

( ) - rstr [20] rstr [8] . tt p1 . , . .

, , - FPU, - . "_control_fp (", "fesetround (" "fenv.h".

+1

, .

, , ( ) "". , (, , "(x + y) + z" "x + (y + z)" ), - (, ), - , ..

, () 80x86 80- " " , , ; ( ) FPU.

Basically, what I'm saying is that if the exact value you get is of great importance, then you shouldn't use floating point at all (consider "great rationalities" or something like that).

-2
source

All Articles