Different floating point representations of identical 64 bit double precision numbers

68 Views Asked by At

I have some Fortran code which forms a handle from the bit-pattern of a structure. It marks two structures as identical when the handle of each is the same.

I am getting different handles for two identical structures (from what I see in the Intel debugger), and have traced it to down to one 64 bit double precision member of the structure. It has the value 1020.0 in both of the structures I am comparing. However the hex representations in memory are different.

st%wd   1020.00000000000    REAL(8) 
loc(st%wd)  #0000021F2ABD78A0   INTEGER(8) 
0x0000021F2ABD78A0  00 00 00 00 00 e0 8f 40

st%wd   1020.00000000000    REAL(8) 
loc(st%wd)  #0000021F2C9C0F60   INTEGER(8) 
0x0000021F2C9C0F60  ff ff ff ff ff df 8f 40

I'm not sure why the bit patterns are different. But this is cause of the different handles I obtain in my code which therefore marks the structures as different.

I was expecting the bit patterns of the two 64 bit floating point numbers to be the same.

2

There are 2 best solutions below

2
John Bollinger On BEST ANSWER

It has the value 1020.0 in both of the structures I am comparing. However the hex representations in memory are different.

Those two statements are inconsistent. On any hardware you are likely to meet in practice, if the representations of two numbers of the same data type are different then the values represented are different.

Note that if you interpret those two representations as 8-byte, little-endian unsigned integers then their values differ by exactly 1. That corresponds in this case to a 1-bit (== 1 ulp) difference between the two double precision values. The 15 decimal digits with which you are printing decimal representations of these numbers are not quite enough to show the difference.

I'm not sure why the bit patterns are different.

They are different because they encode (ever so slightly) different numbers.

0
PierU On

The two floating point values are not the same. They appear to be the same because you don't print them with enough digits:

real(8) :: x

x = 1020d0
write(*,"(F25.15,Z20)") x, transfer(x,0_8)
x = nearest(x,-1.0)
write(*,"(F25.15,Z20)") x, transfer(x,0_8)
end 

gives:

     1020.000000000000000    408FE00000000000
     1019.999999999999886    408FDFFFFFFFFFFF