Big EDIT about big numbers
.
The following code shows the problem with my solution in my other answer.
Please note that I changed the parameter of my hexf2binf (floathex) function from h to floathex to make it the same as the parameter used by unutbu in its floathex_to_binary (floathex) function
from decimal import Decimal,getcontext getcontext.prec = 500 tinies = [ Decimal(1) / Decimal(2**i) for i in xrange(1,400)] com = dict((i,tin) for i,tin in enumerate(tinies,1)) def hexf2binf(floathex, tinies = tinies): fromh = float.fromhex(floathex) print 'fromh = float.fromhex(h) DONE' print 'fromh ==',fromh print "str(float.fromhex(floathex)) ==",str(float.fromhex(floathex)) a,_,p = str(float.fromhex(floathex)).partition('.') print 'before the dot ==',a print 'after the dot ==',p
result
x = 123456789012345685803008.000000 h = x.hex() == 0x1.a249b1f10a06dp+76 ENTERING hexf2binf(floathex) with h as argument fromh = float.fromhex(h) DONE fromh == 1.23456789012e+23 str(float.fromhex(floathex)) == 1.23456789012e+23 before the dot == 1 after the dot == 23456789012e+23 hexf2binf(x)== 0b1.111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
The problem is with the str(float.fromhex(x)) statement in the a,_,p = str(float.fromhex(x)).partition('.') Statement , which expresses the representation of float.fromhex (x) for a large number with an indicator.
Then PARTS BEFORE DATA (a ante) AND AFTER CURRENT (p as a message) EASY.
Fixing this is easy: replacing the inaccurate statement with this:
a,_,p = '{:f}'.format(float.fromhex(x)).partition('.')
.
Nota bene:
On a typical machine running Python, there is 53 bits of precision available for floating Python, so the value is stored internally when you enter the decimal number 0.1 - binary fraction 0.00011001100110011001100110011001100110011001100110011010 http://docs.python.org/tutorial/floatingpoint .html
This means that when a large value for a float is written in the code, its internal representation is actually an approximation to the recorded value. This is shown in the following code:
x1 = 123456789012345685803008.0 print 'x1 == 123456789012345685803008.0' h1 = x1.hex() print 'h1 = x1.hex() ==',h1 y1 = float.fromhex(h1) print 'y1 = float.fromhex(h1) == {:f}'.format(y1) print x2 = 123456789012345678901234.64655 print 'x2 == 123456789012345678901234.64655' h2 = x2.hex() print 'h2 = x2.hex() ==',h2 y2 = float.fromhex(h2) print 'y2 = float.fromhex(h2) == {:f}'.format(y2) print
result
x1 == 123456789012345685803008.0 h1 = x1.hex() == 0x1.a249b1f10a06dp+76 y1 = float.fromhex(h1) == 123456789012345685803008.000000 x2 == 123456789012345678901234.64655 h2 = x2.hex() == 0x1.a249b1f10a06dp+76 y2 = float.fromhex(h2) == 123456789012345685803008.000000
The values ββof h1 and h2 are the same because, although different values ββare assigned to the identifiers x1 and x2 in the script, OBJECTS x1 and x2 are represented with the same approximation in the machine.
The internal representation of 123456789012345685803008.0 is the exact value 123456789012345685803008.0 and is the internal representation of 123456789012345678901234.64655 , but its approximation, therefore, outputting h1 and h2 from x1 and x2 gives the same value of h1 and h2 .
This problem exists when we write a decimal number in a script. This does not exist when we write a number directly in hexadecimal or binary representation.
What I wanted to emphasize
is that I wrote the afterdotbinary2float (sbin, com = com) function to check the results obtained by hexf2binf () . This check works well when the number passed to hexf2binf () is small, but due to the internal approximation of large numbers (= with a lot of digits), I wonder if this check is not distorted. Indeed, when a large number comes into the function, it has already been approximated: the numbers after the point have been converted to a series of zeros,
as shown here after:
from decimal import Decimal, getcontext getcontext().prec = 500 tinies = [ Decimal(1) / Decimal(2**i) for i in xrange(1,400)] com = dict((i,tin) for i,tin in enumerate(tinies,1)) def afterdotbinary2float(sbin, com = com): '''Transforms a binary lying after a dot into a float after a dot''' if sbin.startswith('0b.') or sbin.startswith('.'): sbin = sbin.split('.')[1] if all(c in '01' for c in sbin): return sum(int(c)*com[i] for i,c in enumerate(sbin,1)) else: return None def hexf2binf(floathex, tinies = tinies): '''Transforms an hexadecimal float with a dot into a binary float with a dot''' a,_,p = '{:.400f}'.format(float.fromhex(floathex)).partition('.')
result
n == 123456789012345685803008.000000 transformed with its method hex() to: nhexed = n.hex() == 0x1.a249b1f10a06dp+76 hexf2binf(nhexed) == 0b11010001001001001101100011111000100001010000001101101000000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Verification: before,_,after = hexf2binf(nhexed).partition('.') before == 0b11010001001001001101100011111000100001010000001101101000000000000000000000000 after == 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 int(before,2) == 123456789012345685803008 afterdotbinary2float(after) == 0E-399 --------------------------------------------------------------- n == 123456789012345685803008.000000 transformed with its method hex() to: nhexed = n.hex() == 0x1.a249b1f10a06dp+76 hexf2binf(nhexed) == 0b11010001001001001101100011111000100001010000001101101000000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Verification: before,_,after = hexf2binf(nhexed).partition('.') before == 0b11010001001001001101100011111000100001010000001101101000000000000000000000000 after == 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 int(before,2) == 123456789012345685803008 afterdotbinary2float(after) == 0E-399 --------------------------------------------------------------- n == 123456789012345.2546 transformed with its method hex() to: Traceback (most recent call last): File "I:\verfitruc.py", line 41, in <module> nhexed = n.hex() AttributeError: 'Decimal' object has no attribute 'hex'
Conclusion: testing with numbers 123456789012345685803008.0 and 123456789012345678901234.64655 has no meaning and is not of interest.
So, I wanted to check for unapproximated numbers, and I passed in a floating point number. As you can see, the problem is that such an instance does not have a hex () method.
.
Finally, I'm not quite sure of my function for large numbers, but it works correctly for common numbers after I corrected an inaccurate instruction.
.
EDIT
I added '.400' to the statement:
a,_,p = '{:.400f}'.format(fromh).partition('.')
otherwise, the value of p can be truncated, which gives a binary representation of a slightly different number than the value passed to the function.
I put 400 because it is the length that I defined for the tinies list, which contains decimal instances corresponding to 1/2, 1/4, 1/8, 1/16, etc.
However, although it rarely happens that a number with more than 400 digits after the decimal point makes any sense, this addition remains unsatisfactory to me: the code is not absolutely general, which is the case of unutbu code.