2010-12-13 63 views
1

Je veux convertir un flottant (la sortie de time.time()) en hexadécimal en utilisant python 2.4/2.5.python 2.5: comment convertir float en hexa?

J'ai trouvé des tonnes d'exemples qui convertissent des hexs en float, mais je ne trouve rien qui me permette de faire ce que fait le float.hex() de python> = 2.6.

+0

Il serait utile si vous avez dit POURQUOI vous voulez faire cela, par exemple. qu'est-ce qui va consommer la chaîne hexagonale? –

+0

J'en ai besoin pour créer un identifiant unique (avec d'autres choses). Si vous voulez savoir pourquoi, la réponse est: ce n'est pas mon choix. –

+0

Si vous n'avez pas besoin d'être en mesure de récupérer l'heure à partir de l'identifiant unique, et que vous souhaitez simplement obtenir des nombres différents, essayez hash (time.time()) pour obtenir un entier et hex (hash (time. time())) pour obtenir une chaîne au format '0xBLAHBLAH'. –

Répondre

3

Il ne peut pas être fait de manière portative en Python avant la version 2.6; il a besoin des informations dans sys.float_info, ce qui est nouveau dans Python 2.6. Si vous voulez le faire de façon non portative, c'est-à-dire pour votre plate-forme particulière, vous devrez regarder le fichier float.h pour le compilateur C qui a été utilisé pour produire votre Python 2.4/5, ou sur sys.float_info renvoyé par une implémentation 2.6 ou 2.7 sur votre plate-forme (et confiant qu'elle s'applique à votre Python 2.4/5). Ensuite, vous devriez regarder la fonction float_hex dans la source Python (Objects/floatobject.c) et la traduire en Python et la tester (par rapport à un Python 2.6/7, peut-être).

Cela semble beaucoup de travail, pour quoi faire? Quel est ton but? Que voulez-vous faire qui ne peut être atteint avec repr(your_float)?

Modifier: besoin d'un identifiant unique

Note que time.time() ne sont pas très précis:

"" » time.time() Retourne le temps en virgule flottante Notez que même si l'heure est toujours renvoyée sous la forme d'un nombre à virgule flottante, tous les systèmes n'offrent pas une précision supérieure à 1 seconde, alors que cette fonction renvoie normalement des valeurs non décroissantes. peut renvoyer une valeur inférieure à celle d'un appel précédent si l'horloge système a été rétablie entre les deux appels « » »

permettant jusqu'à un milliardième de seconde résolution:

>>> hex(int(time.time() * 1000000000)) 
'0x11ef11c41cf98b00L' 
>>> 

Est-ce suffisant?

1

Voici la version C du code, je n'ai pas le temps de le porter en ce moment, mais peut-être quelqu'un d'autre le peut.

float_hex(PyObject *v) 
{ 
    double x, m; 
    int e, shift, i, si, esign; 
    /* Space for 1+(TOHEX_NBITS-1)/4 digits, a decimal point, and the 
     trailing NUL byte. */ 
    char s[(TOHEX_NBITS-1)/4+3]; 

    CONVERT_TO_DOUBLE(v, x); 

    if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) 
     return float_str((PyFloatObject *)v); 

    if (x == 0.0) { 
     if (copysign(1.0, x) == -1.0) 
      return PyString_FromString("-0x0.0p+0"); 
     else 
      return PyString_FromString("0x0.0p+0"); 
    } 

    m = frexp(fabs(x), &e); 
    shift = 1 - MAX(DBL_MIN_EXP - e, 0); 
    m = ldexp(m, shift); 
    e -= shift; 

    si = 0; 
    s[si] = char_from_hex((int)m); 
    si++; 
    m -= (int)m; 
    s[si] = '.'; 
    si++; 
    for (i=0; i < (TOHEX_NBITS-1)/4; i++) { 
     m *= 16.0; 
     s[si] = char_from_hex((int)m); 
     si++; 
     m -= (int)m; 
    } 
    s[si] = '\0'; 

    if (e < 0) { 
     esign = (int)'-'; 
     e = -e; 
    } 
    else 
     esign = (int)'+'; 

    if (x < 0.0) 
     return PyString_FromFormat("-0x%sp%c%d", s, esign, e); 
    else 
     return PyString_FromFormat("0x%sp%c%d", s, esign, e); 
} 
1

Bien sûr, cela peut être fait de manière portable, c'est juste mathématique. Voici comment (en incluant des tests prouvant que cela fonctionne).

from __future__ import division 

MAXHEXADECIMALS = 10 

def float2hex(f): 
    w = f // 1 
    d = f % 1 

    # Do the whole: 
    if w == 0: 
     result = '0' 
    else: 
     result = '' 
    while w: 
     w, r = divmod(w, 16) 
     r = int(r) 
     if r > 9: 
      r = chr(r+55) 
     else: 
      r = str(r) 
     result = r + result 

    # And now the part: 
    if d == 0: 
     return result 

    result += '.' 
    count = 0 
    while d: 
     d = d * 16 
     w, d = divmod(d, 1) 
     w = int(w) 
     if w > 9: 
      w = chr(w+55) 
     else: 
      w = str(w) 
     result += w 
     count += 1 
     if count > MAXHEXADECIMALS: 
      break 

    return result 


import unittest 
class Float2HexTest(unittest.TestCase): 

    def test_ints(self): 
     assert float2hex(0x25) == '25' 
     assert float2hex(0xFE) == 'FE' 
     assert float2hex(0x00) == '0' 
     assert float2hex(0x01) == '1' 
     assert float2hex(0x14E7F400A5) == '14E7F400A5' 

    def test_floats(self): 
     assert float2hex(1/2) == '0.8' 
     assert float2hex(1/13) == '0.13B13B13B13' 
     assert float2hex(1034.03125) == '40A.08' 

suite = unittest.makeSuite(Float2HexTest) 
runner = unittest.TextTestRunner() 
runner.run(suite) 

Oui, c'est plutôt inutile. :-) Bien sûr, la bonne réponse dans ce cas est de ne pas convertir un flottant en hexadécimal, mais d'utiliser une représentation INTEGER du temps et de le convertir en une chaîne hexadécimale. Mais encore, cela peut être fait. :)