简体   繁体   中英

converting 41digit float to hexadecimal

I am playing around with some RSA crypto calculations and one of them is calculating

very-large-number**(1/3)

where very large number is 100 digits. I need the result as hexadecimal in the end to get the final result.

I have tried the usual float.hex() hex(int(n)) and even some of the prosed solutions from here Dealing with very large hex numbers in python

but the result I get is either in scientific format (xx.xxxx+40) or the last half of the outout is all 0 (which I know is not correct)

Example:

>>> n=14887716705766614226302331656748546195328906880296894322596715261404953788693951344841626882745910926946567107240171862117
>>> ct=n**(1/3)
>>> ct.hex()
'0x1.212d39ed89671p+134'
>>> print(ct)
2.4600430019674926e+40
>>> print(ct.hex())
0x1.212d39ed89671p+134
hex(int(ct))
'0x484b4e7b6259c400000000000000000000'
>>> int(ct)
24600430019674926067273894051435979472896

so how do I get the hex value out? the first part)0x484b4e7b6259c) from hex(int(ct)) is correct so this seem to indicate precision error.

I have also tried with numpy:

>>> import numpy as np
>>> x=np.longdouble(14887716705766614226302331656748546195328906880296894322596715261404953788693951344841626882745910926946567107240171862117)
>>> float_formatter='{e:f}'.format
>>> np.set_printoptions(formatter={'float_kind':float_formatter},precision=128)
>>> ct=np.cbrt(x)
>>> np.cbrt(x)
2.4600430019675053399e+40
>>> print(ct)
2.4600430019675053399e+40

Edit: the actual result for the calculations should be: 24600430019675053398291607284547696341373 before hex which should turn into 0x484B4E7B625A2D53644D2D64644F72317D as hex

The problem is that while Python integers are multi-precision numbers, floats are only 64 bits IEEE 754 floating point numbers and have a precision limited to 15 or 16 decimal digits.

That means that the floating point n ** (1/3) operation will only give an approximation. But you could use Newton method to find a more accurate solution of the equation x**3 = n:

def sqr3(n):
    s0 = int(n ** (1/3))
    s1 = 0
    while True:
        s1 = s0 + (n - s0 **3) // 2 // s0 // s0
        if s1 ** 3 == n:
            break
        if (s0 - 1 <= s1 <= s0 + 1):
            # should search further whether s0 or s1 (or maybe next iteration)
            #  would be the best one...
            break
        s0 = s1
    return s1

It gives for sqr3(n) : 24600430019675053398291607284547696341373 which is the exact solution.

Doing a quick check with an existing online converter , your two outputs are in fact the same number

'0x484b4e7b6259c400000000000000000000'

equals

24600430019674926067273894051435979472896

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM