[Tutor] Need a better name for this function

Richard D. Moores rdmoores at gmail.com
Wed Dec 16 23:48:38 CET 2009


On Wed, Dec 16, 2009 at 02:48, Dave Angel <davea at ieee.org> wrote:
> Richard D. Moores wrote:

> If you really want to see what binary fp does, you might need to resort to
> hex.  Two methods of float are relevant, hex() and fromhex().  Check out the
> following function I just wrote.
>
> import decimal
> float2decimal = decimal.Decimal.from_float
>
> a = 0.1
> print("internal repr of 0.1 is ", a.hex())    # 0x1.999999999999ap-4
>
>
> def test(stringval):
>   floatval = float.fromhex(stringval)
>   decimalval = float2decimal(floatval)
>   print( stringval, "--", floatval, "--", decimalval )
>
>
> test(" 0x1.9999999999999p-4")
> test(" 0x1.999999999999ap-4")    #This is 0.1, as best as float sees it
> test(" 0x1.999999999999bp-4")
>
>
> The output is (re-wordwrapped for email):
>
> internal repr of 0.1 is  0x1.999999999999ap-4
> 0x1.9999999999999p-4 -- 0.1
>    -- 0.09999999999999999167332731531132594682276248931884765625
> 0x1.999999999999ap-4 -- 0.1
>    -- 0.1000000000000000055511151231257827021181583404541015625
> 0x1.999999999999bp-4 -- 0.1
>    -- 0.10000000000000001942890293094023945741355419158935546875
>
> Notice that these are the closest values to 0.1 that can be represented in a
> float, one below, and the first two above.  You can't get any values between
> those.  When you print any of them, it shows a value of 0.1, presumably due
> to rounding during conversion to a decimal string.  The algorithm used in
> such conversion has changed many times in the evolution of CPython.
>
> And in case it's not obvious, the stringval items are 14 hex digits (56
> bits), plus the letter "p", a sign, and an exponent value.  These are
> encoded into 64bits as a float.

Dave, that's enlightening. Thanks very much.

>You can see such a value for any float you
> like, by using the method hex() on the float object.

Yes, I'd like to generalize that and include it in my function
(renamed of course). How can I compute the equivalents of your
"0x1.9999999999999p-4 -- 0.1" and "0x1.999999999999bp-4 -- 0.1", which
are, respectively, the closest hex value to a.hex() that is smaller
than a.hex(), and the the closest hex value to a.hex() that is greater
than a.hex()?

This is what I have so far:
======================================================
import decimal
float2decimal = decimal.Decimal.from_float

a = .435
stringval = a.hex()
print("internal repr of", a, "is ", stringval)


def test(stringval):
    floatval = float.fromhex(stringval)
    decimalval = float2decimal(floatval)
    print( stringval, "--", floatval, "--", decimalval )

test(stringval)

OUTPUT:
internal repr of 0.435 is  0x1.bd70a3d70a3d7p-2
0x1.bd70a3d70a3d7p-2 -- 0.435 --
0.434999999999999997779553950749686919152736663818359375
=============================================

Thanks,

Dick


More information about the Tutor mailing list