Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #112097

Re: Float

From eryk sun <eryksun@gmail.com>
Newsgroups comp.lang.python
Subject Re: Float
Date 2016-07-30 18:19 +0000
Message-ID <mailman.60.1469902801.6033.python-list@python.org> (permalink)
References (3 earlier) <579c82a6$0$1619$c3e8da3$5496439d@news.astraweb.com> <e5d77dc3-2fe4-4352-9582-8a259f3c4f9d@googlegroups.com> <CAPTjJmri1uAicp_VnZ+b3+goWASGkW4yaAKJdLqcbs2N72Sz_Q@mail.gmail.com> <apjppbtocn2vs6v581clq8470on5b14sce@4ax.com> <CACL+1avNFd0+1fJ5mc5DC=rq+RHg7wefRfwUdmW6pno6KOpiUg@mail.gmail.com>

Show all headers | View raw


On Sat, Jul 30, 2016 at 4:03 PM, Dennis Lee Bieber
<wlfraed@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.

Back to comp.lang.python | Previous | NextPrevious in thread | Find similar | Unroll thread


Thread

Float Cai Gengyang <gengyangcai@gmail.com> - 2016-07-29 02:44 -0700
  Re: Float Lutz Horn <lutz.horn@posteo.de> - 2016-07-29 11:56 +0200
  Re: Float Ben Finney <ben+python@benfinney.id.au> - 2016-07-29 20:25 +1000
  Re: Float Steven D'Aprano <steve@pearwood.info> - 2016-07-30 00:26 +1000
    Re: Float Cai Gengyang <gengyangcai@gmail.com> - 2016-07-30 03:21 -0700
      Re: Float Steven D'Aprano <steve@pearwood.info> - 2016-07-30 20:34 +1000
        Re: Float Cai Gengyang <gengyangcai@gmail.com> - 2016-07-30 04:44 -0700
          Re: Float Chris Angelico <rosuav@gmail.com> - 2016-07-30 21:51 +1000
            Re: Float Rustom Mody <rustompmody@gmail.com> - 2016-07-30 20:20 -0700
              Re: Float Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-08-04 00:28 -0700
          Re: Float Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2016-07-30 12:03 -0400
          Re: Float eryk sun <eryksun@gmail.com> - 2016-07-30 18:19 +0000

csiph-web