On Sat, Jul 30, 2016 at 4:03 PM, Dennis Lee Bieber <wlfr...@ix.netcom.com> wrote: > And in a rather convoluted route, one can get to the underlying > representation... > >>>> import struct >>>> f = struct.pack(">f", 3.0) >>>> i = struct.pack(">i", 3) >>>> fi = struct.unpack(">i", f) >>>> ii = struct.unpack(">i", i) #really a waste of time >>>> "0x%8.8X 0x%8.8X" % (fi[0], ii[0]) > '0x40400000 0x00000003'
A CPython float is a C double-precision float ('d'), which is an IEEE 754 binary64 on all of CPython's supported platforms. This format has a precision of 15 decimal digits (rounded down from 15.95). Uniquely representing a C double requires 17 decimal digits. See the following Wikipedia article for more information: https://en.wikipedia.org/wiki/Double-precision_floating-point_format The underlying representation of 3.0 is as follows: >>> n = 3.0 >>> hex(struct.unpack('Q', struct.pack('d', n))[0]) '0x4008000000000000' You can confirm this by attaching a native debugger (such as gdb on Linux or cdb on Windows) and pointer casting the float object's ob_fval field as a uint64_t integer: Linux (python3-dbg): >>> id(n) 140737353618480 (gdb) p/x *(uint64_t *)&((PyFloatObject *)140737353618480)->ob_fval $1 = 0x4008000000000000 Windows (python_d.exe): >>> id(n) 2398135104848 0:000> ?? *(ULONG64 *)&((PyFloatObject *)2398135104848)->ob_fval unsigned int64 0x40080000`00000000 We can break this down as follows: sign = 0x400 >> 11 = 0 exponent = (0x400 & (1 << 11 - 1)) - 1023 = 1 significand = 1 + 0x8000000000000 / 2 ** 52 = 1.5 n = (-1) ** sign * significand * 2 ** exponent = 3.0 Python's float type has a hex() method that represents the value in hexadecimal as follows: >>> n.hex() '0x1.8000000000000p+1' This format shows the implicit integer bit of the normalized significand and decodes the sign and exponent values for you. -- https://mail.python.org/mailman/listinfo/python-list