Skip to content

Instantly share code, notes, and snippets.

@ocelotl
Created October 13, 2022 12:28
Show Gist options
  • Save ocelotl/9f7bf05743dd827fa0220dd14436fe17 to your computer and use it in GitHub Desktop.
Save ocelotl/9f7bf05743dd827fa0220dd14436fe17 to your computer and use it in GitHub Desktop.
Function that converts floating point values into their IEEE 754 representation
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