Search code examples
pythonfloating-pointieee-754exponent

How to calculate mantissa in python when exponent hit to -127


I've got a location information in HEX string. I need to convert it into floating integer by IEEE-754 protocol.

So I wrote this code to find sign of the number, compute exponent and mantissa from binary representation of the given hexadecimal number.

def _calculte_mantissa(bin_number):
    val = 1
    bit_count = -1
    bit_length = 0
    while bit_length <= 22:
        print bit_count, bit_length
        val += int(bin_number[bit_length]) * 2**bit_count
        bit_count -= 1
        bit_length += 1
        print val
    return val

def convert_position(pos):
    bin_pos = format(int(pos, 16), "0>32b")
    sign = (-1)**int(bin_pos[0], 2)
    exponent = int(bin_pos[1:9], 2) - 127
    mantissa = _calculte_mantissa(bin_pos[9:])
    position = sign * 2**exponent * mantissa
    return position

The problem is; If exponent is little than -126, say -127, the result is not correct. I check the result from this address, sign and exponent results are correct but mantissa result is different than mine.

I am missing something about the what that page is saying:

As a result, the mantissa has a value between 1.0 and 2. If the exponent reaches -127 (binary 00000000), the leading 1 is no longer used to enable gradual underflow.

Anyway, I know the problem is here, but I can't figure out because of my insufficient English.


Solution

  • After suggestion of @Rudy Velthuis I figured out that I need to remove 1.0 and calculate with exponent -126 if exponent hit to -127. So the result is:

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys
    
    
    def _calculte_mantissa(bin_number, exponent):
        val = 1 if exponent > -127 else 0
        bit_count = -1
        bit_length = 0
        while bit_length <= 22:
            val += int(bin_number\[bit_length\]) * 2**bit_count
            bit_count -= 1
            bit_length += 1
        return val
    
    
    def convert_ieee754(hex_val):
        bin_pos = format(int(hex_val, 16), "0>32b")
        sign = (-1)**int(bin_pos\[0\], 2)
        _exponent = int(bin_pos\[1:9\], 2) - 127
        mantissa = _calculte_mantissa(bin_pos\[9:\], _exponent)
        exponent = _exponent if _exponent > -127 else -126
        position = sign * 2**exponent * mantissa
        return "Bin: %s - Sign: %s - Exponent: %s (%s) - Mantissa: %s - Posititon: %s" % (bin_pos, sign, exponent,
                                                                                          _exponent, mantissa, position)
    
    
    if __name__ == "__main__":
        argvs = sys.argv
        print convert_ieee754(argvs\[1\])
        sys.exit()
    

    https://github.com/RecNes/Python-IEEE754-Calculator-with-Denormalized-Values/blob/master/ieee754.py