简体   繁体   中英

double precision floating point

I am trying to read in binary, eight-byte floats and convert them to decimal. I am able to read in and convert English word unsigned 8-bit ASCII with no problem. If the byte order for the double precision is the same as the byte order for the 1-byte characters, I should be able to replicate the values of a header file that I have looked up in its own dedicated software. Here is what one of the header classes does in fact have in its header, as gained from the dedicated software for that purpose: "Class 3

  utdate:      2022.051500

      ut:         7.089062

     lst:        15.180985

 norchan:         1.000000

 noswvar:         1.000000

 nophase:         1.000000

 cycllen:         1.000000

 samprat:        30.000000

cl11type:         PROTO12M

"

Here are the bit strings I get for this section of header using a python script to extract the bytes: " Class 3 Header Observing Parameters

01000000 10011111 10011000 00110100 10111100 01101010 01111110 11111010

01000000 00011011 11111100 10111000 00001000 10111011 11101011 00010001

01000000 00101110 00101101 01001011 01010010 01111100 11001000 01000000

00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000

00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000

00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000

00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000

01000000 00111110 00000000 00000000 00000000 00000000 00000000 00000000

01001101 00110010 00110001 01001111 01010100 01001111 01010010 01010000 "

I am able to reproduce the math, I THINK, that goes into the fields that say "1.000000". That math is: +1 * 2^(1023-1023) * (1 + .0) = +1 * 2^0 * 1.0 = 1 * 1.0 = 1.000000

I am NOT able to reproduce the math that I THINK should go into the field that says 30.000000: +1 * 2^(1027-1023) * (1 + .1970324836974592) = +1 * 2^4 * 1.1970324836974592 = 16 * 1.1970324836974592 = 19.152519739159347.

I have attempted to reproduce the double precision calculation on many values that are in the 10-10000 range, and my result is invariably something like two-thirds of what the value should be.

Can someone demonstrate the proper calculation using these bit strings, or, confirm that the bit strings MUST be incorrect? (I cannot understand how they're incorrect because, using this extraction of bytes, I am matching 9 unique 8 or 16 character ASCII strings in preceding header classes...

(Here's me attempting that first one, the year of 2022:

2^(1033-1023) * (1 + .4389476917477114) = 1024 * 1.4389476917477114 = 1473.482436349656474

Here, 1473 is like 3/4 of 2022...)

Thank you

I'm not sure why you have converted them to binary, but what you have there are just 8-byte double-precision floats. You can convert them as they are.

bits = """\
01000000 10011111 10011000 00110100 10111100 01101010 01111110 11111010 
01000000 00011011 11111100 10111000 00001000 10111011 11101011 00010001
01000000 00101110 00101101 01001011 01010010 01111100 11001000 01000000
00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000
00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000
00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000
00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000
01000000 00111110 00000000 00000000 00000000 00000000 00000000 00000000
01001101 00110010 00110001 01001111 01010100 01001111 01010010 01010000"""

import struct

for line in bits.splitlines():
    by = bytes(reversed([int(k,2) for k in line.split()]))
    print(by)
    z = struct.unpack('d',by)[0]
    print(z)

Output:

b'\xfa~j\xbc4\x98\x9f@'
2022.0515
b'\x11\xeb\xbb\x08\xb8\xfc\x1b@'
6.996795784444445
b'@\xc8|RK-.@'
15.088465287906843
b'\x00\x00\x00\x00\x00\x00\xf0?'
1.0
b'\x00\x00\x00\x00\x00\x00\xf0?'
1.0
b'\x00\x00\x00\x00\x00\x00\xf0?'
1.0
b'\x00\x00\x00\x00\x00\x00\xf0?'
1.0
b'\x00\x00\x00\x00\x00\x00>@'
30.0
b'PROTO12M'
7.484008430422714e+63

Here's how you unpack these numbers. Let's look at 30, which is

403E000000000000
0100 0000 0011 1110 0000....

There are three fields here: sign, exponent, mantissa:

0  100 0000 0011  1110 0000...
-- -------------  ------------
S  exponent       mantissa

The sign bit is positive. The exponent is 0x403, which means the exponent is 2**4 . There is an assumed "one bit" at the left end of the mantissa on the other side of the "decimal" point, so the fraction we have is 1.111. If we multiply that by 2**4 , we get 11110, which is 30.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM