[Tutor] Need a better name for this function

Dave Angel davea at ieee.org
Thu Dec 17 05:23:01 CET 2009


Richard D. Moores wrote:
> On Wed, Dec 16, 2009 at 14:48, Richard D. Moores <rdmoores at gmail.com> wrote:
>
> I just realized that my question was absurd, in that given real
> numbers n and x there is no x such that both x < n and x is greater
> than all other numbers less than n.
>
> So after inserting "(in 14 hex digits)" at 2 places, my question is:
>
> 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 (in 14 hex digits) to a.hex()
> that is smaller
> than a.hex(), and the the closest hex value (in 14 hex digits) 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
>>
>>     
>
>   

There are conceivably better ways to get at the mantissa of the fp number, but you can simply parse the hex digits as I did manually, and add one and subtract one from the given mantissa  (the part between the decimal point and the 'p').  Then it just remains to figure out which two of those three values actually span the desired value.

Using the numbers and strings you supply, the three values would be:

0x1.bd70a3d70a3d6p-2
0x1.bd70a3d70a3d7p-2
0x1.bd70a3d70a3d8p-2


and the second one is somewhat less than .435, while the 3rd is more.

Now, while this is good enough to do by hand, you have to realize there 
are some places it may not work, and another where it won't.

I'm not sure whether trailing zeroes are always provided in the hex() 
method.  So you may have to pad it out before adjusting the last digit.  
I'm also not positive how it normalizes the hex value printed out.  As 
the example in the help indicates, there are more than one hex string 
that can be converted to the same float - if you denormalize, it'll 
still convert it.  I just don't know if hex() ever produces a 
non-normalized value.

More drastically, if you're trying to be complete, is the infinities, 
the NAN values, and the numbers, *very* close to zero, where gradual 
underflow takes effect.  The notion here is that when the exponent gets 
as negative as it can safely store, the standard requires that the 
number be stored denormalized, rather than going immediately to zero.  I 
don't know how those values are represented by the hex() method, but 
they have fewer significant digits, so the adjustment you would need 
would be in a different column.


If I had to write a function to do what you ask, and if I couldn't get 
better specs as to what Python is actually doing with the hex() method, 
I'd work out an algorithm where tweak what seems to be the bottom digit, 
then see if the float has a new value.  If it does not, I'm working on 
the wrong column.

DaveA



More information about the Tutor mailing list