Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Extract double in binary file
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Francis Avila  
View profile  
 More options Nov 28 2003, 4:46 am
Newsgroups: comp.lang.python
From: "Francis Avila" <francisgav...@yahoo.com>
Date: Fri, 28 Nov 2003 04:45:31 -0500
Local: Fri, Nov 28 2003 4:45 am
Subject: Re: Extract double in binary file

Dennis Lee Bieber wrote in message ...
>Pascal fed this fish to the penguins on Thursday 27 November 2003 01:07
>am:

>> Some precisions:
>> 0.00 > 00-00-00-00-00-00-7F-00
>> 1.00 > 00-00-00-00-00-00-00-81
>> 2.00 > 00-00-00-00-00-00-00-82
>> 3.00 > 00-00-00-00-00-00-40-82
>> 4.00 > 00-00-00-00-00-00-00-83

>> 10.00 > 00-00-00-00-00-00-20-84
>> 1000.00 > 00-00-00-00-00-00-7A-8A

>> 1.11 > 14-AE-47-E1-7A-14-0E-81
>converting exponents excess 81...

>        0 1 00 00 00 00 00 00 00
>        1 1 00 00 00 00 00 00 00
>        1 1 40 00 00 00 00 00 00
>        2 1 00 00 00 00 00 00 00
>        3 1 20 00 00 00 00 00 00

That is a bizarre format, and of course I had to implement it. (Even C is
more pleasant in Python!).

It works for the cases given, but do find out where the sign bit is for the
mantissa. (This code assumes it's the MSB of the mantissa.)

Also tease out the NaN and +-Infinity cases.

--- Code ---
#! /usr/bin/env python
# by Francis Avila
#
# Decode a peculiar binary floating point encoding
# used by 'multilog', an old dos spreadsheet.

import struct

_known = (('0.00', '\x00\x00\x00\x00\x00\x00\x7F\x00'),
         ('1.00', '\x00\x00\x00\x00\x00\x00\x00\x81'),
         ('2.00', '\x00\x00\x00\x00\x00\x00\x00\x82'),
         ('3.00', '\x00\x00\x00\x00\x00\x00@\x82'),
         ('4.00', '\x00\x00\x00\x00\x00\x00\x00\x83'),
         ('10.00','\x00\x00\x00\x00\x00\x00 \x84'),
         ('1000.00','\x00\x00\x00\x00\x00\x00z\x8a'),
         ('1.11', '\x14\xaeG\xe1z\x14\x0e\x81'))

def _test():
    tests = [(str(float(i)),str(dectofloat(j))) for i,j in _known]
    results = [expect==got for expect,got in tests]

    failed = [tests[i] for i, passed in enumerate(results) if not passed]

    if failed: return failed
    else: return 'Passed'

def bin(I):
    """Return list of bits of int I in little endian."""
    if I < 0:
        raise ValueError, "I must be >= 0"
    bits = []
    if I == 0:
        bits = [0]
    while I>0:
        r = (I & 0x1)
        if r: r = 1
        bits.append(r)
        I >>= 1
    bits.reverse()
    return bits

def binaryE(n, exp):
    """Return result of a binary n*10**exp.

    As n*10**exp is to decimal, so binaryE(n, exp) is to binary.
    """
    return sum([2**(exp-i) for i,bit in enumerate(bin(n)) if bit])

#Add special cases here:
SPECIAL = {'\x00\x00\x00\x00\x00\x00\x7f\x00':0.0}

def dectofloat(S):
    """Return float value of 8-byte 'decimal' string."""
    if S in SPECIAL:
        return SPECIAL[S]

    # Convert to byteswapped long.
    N, = struct.unpack('<Q', S)

    # Grab exponent and mantissa parts using bitmasks.
    # The eight MSBs are exponent; rest mantissa.
    exp, mant = (N&(0xffL<<56))>>56, N&~(0xffL<<56)

    exp -= 0x81 # Exponential part is excess 0x81 (e.g., 0x82 is 1).

    msign = mant & (0x80L<<48) # MSB of mantissa is sign bit. 0==positive.
    if not msign:
        msign = 1
    else:
        msign = -1

    mant |= (0x80L<<48) # Add implied 1 to the MSB of mantissa.

    # Now, binary scientific notation:

    return float(msign * binaryE(mant, exp))


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.