Created
October 13, 2022 12:28
-
-
Save ocelotl/9f7bf05743dd827fa0220dd14436fe17 to your computer and use it in GitHub Desktop.
Function that converts floating point values into their IEEE 754 representation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ctypes import c_double, c_uint64 | |
from decimal import Decimal | |
from unittest import TestCase | |
def get_ieee_754_representation(value: float): | |
""" | |
The purpose of this function is to illustrate the IEEE 754 64-bit float | |
representation. | |
This function gets a floating-point value and returns a dictionary with | |
its components separated. The returned dictionary has the following keys: | |
sign: the sign bit | |
exponent: the exponent bits | |
mantissa: the mantissa bits | |
decimal: the actual decimal value of the IEEE 754 representation of the | |
original floating-point value. The IEEE 754 representation of | |
floating-point values is discrete, so not all floating point values can be | |
represented exactly. | |
""" | |
result = bin(c_uint64.from_buffer(c_double(value)).value)[2:] | |
if result == "0": | |
result = result * 64 | |
if value > 0: | |
result = f"0{result}" | |
decimal_exponent = 0 | |
exponent = result[1:12] | |
for index, bit in enumerate(reversed(exponent)): | |
if int(bit): | |
decimal_exponent += 2**index | |
# 0 has a special representation in IEEE 574, all exponent and mantissa | |
# bits are 0. The sign bit still represents its sign, so there is 0 (all | |
# bits are set to 0) and -0 (the first bit is 1, the rest are 0). | |
if value == 0: | |
implicit_bit = 0 | |
else: | |
implicit_bit = 1 | |
decimal_exponent -= 1023 * implicit_bit | |
decimal_mantissa = Decimal(implicit_bit) | |
mantissa = result[12:] | |
for index, bit in enumerate(mantissa): | |
if int(bit): | |
decimal_mantissa += Decimal(1) / Decimal(2 ** (index + 1)) | |
sign = result[0] | |
return { | |
"sign": sign, | |
"exponent": exponent, | |
"mantissa": mantissa, | |
# IEEE 754 can only exactly represent a discrete series of numbers, the | |
# intention of this field is to show the actual decimal value that is | |
# represented. | |
"decimal": str( | |
Decimal(-1 if int(sign) else 1) | |
* Decimal(2**decimal_exponent) | |
* decimal_mantissa | |
), | |
} | |
class TestExponential(TestCase): | |
def test_get_ieee_754_representation(self): | |
""" | |
Bit 0: 1 for negative values, 0 for positive values | |
Bits 1 - 11: exponent, subtract 1023 from it to get the actual value | |
Bits 12 - 63: mantissa, a leading 1 is implicit | |
""" | |
# 0 | |
# 10000000001 == 1025 -> 1025 - 1023 == 2 | |
# 0000000000000000000000000000000000000000000000000000 | |
result = get_ieee_754_representation(4.0) | |
self.assertEqual(result["sign"], "0") | |
self.assertEqual(result["exponent"], "10000000001") | |
self.assertEqual( | |
result["mantissa"], | |
"0000000000000000000000000000000000000000000000000000", | |
) | |
self.assertEqual(result["decimal"], "4") | |
result = get_ieee_754_representation(4.5) | |
self.assertEqual(result["sign"], "0") | |
self.assertEqual(result["exponent"], "10000000001") | |
self.assertEqual( | |
result["mantissa"], | |
"0010000000000000000000000000000000000000000000000000", | |
) | |
self.assertEqual(result["decimal"], "4.500") | |
result = get_ieee_754_representation(-4.5) | |
self.assertEqual(result["sign"], "1") | |
self.assertEqual(result["exponent"], "10000000001") | |
self.assertEqual( | |
result["mantissa"], | |
"0010000000000000000000000000000000000000000000000000", | |
) | |
self.assertEqual(result["decimal"], "-4.500") | |
result = get_ieee_754_representation(0.0) | |
self.assertEqual(result["sign"], "0") | |
self.assertEqual(result["exponent"], "00000000000") | |
self.assertEqual( | |
result["mantissa"], | |
"0000000000000000000000000000000000000000000000000000", | |
) | |
self.assertEqual(result["decimal"], "0") | |
result = get_ieee_754_representation(-0.0) | |
self.assertEqual(result["sign"], "1") | |
self.assertEqual(result["exponent"], "00000000000") | |
self.assertEqual( | |
result["mantissa"], | |
"0000000000000000000000000000000000000000000000000000", | |
) | |
self.assertEqual(result["decimal"], "-0") | |
result = get_ieee_754_representation(4.3) | |
self.assertEqual(result["sign"], "0") | |
self.assertEqual(result["exponent"], "10000000001") | |
self.assertEqual( | |
result["mantissa"], | |
"0001001100110011001100110011001100110011001100110011", | |
) | |
self.assertEqual(result["decimal"], "4.299999999999999822364316064") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment