Python 2.5: как конвертировать float в hex? - PullRequest
1 голос
/ 13 декабря 2010

Я хочу преобразовать число с плавающей запятой (вывод time.time()) в шестнадцатеричный формат, используя python 2.4 / 2.5.

Я нашел тонны примеров, которые конвертируют hex в float, но я не могу найти ничего, что позволило бы мне сделать то, что делает float.hex() в python> = 2.6.

Ответы [ 3 ]

3 голосов
/ 13 декабря 2010

Это невозможно сделать в Python до версии 2.6;ему нужна информация в sys.float_info, которая является новой в Python 2.6.

Если вы хотите сделать это не переносимым, то есть для вашей конкретной платформы, вам нужно будет посмотреть файл float.h длякомпилятор C, который использовался для создания вашего Python 2.4 / 5, или в sys.float_info, возвращенном реализацией 2.6 или 2.7 на вашей платформе (и верьте, что он применим к вашему Python 2.4 / 5).Затем вам нужно будет взглянуть на функцию float_hex в исходном коде Python (Objects / floatobject.c) и перевести ее на Python и протестировать ее (возможно, на Python 2.6 / 7).

Это кажетсянравится много работы, для чего?Какова ваша цель?Что вы хотите сделать, чего нельзя достичь с помощью repr(your_float)?

Редактировать : нужен уникальный идентификатор

Обратите внимание, что time.time ()не очень точно:

"" "time.time () Возвращает время в виде числа с плавающей запятой, выраженного в секундах с начала эпохи в UTC. Обратите внимание, что, хотя время всегда возвращается как число с плавающей запятойНе все системы предоставляют время с точностью, превышающей 1 секунду. Хотя эта функция обычно возвращает неубывающие значения, она может возвращать более низкое значение, чем предыдущий вызов, если между двумя вызовами установлены системные часы. "" "

Разрешение с точностью до миллиардной доли секунды:

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

Это достаточно хорошо?

1 голос
/ 14 декабря 2010

Конечно, это можно сделать переносным способом, это просто математика. Вот как это делается (включая тесты, доказывающие, что это работает).

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)

Да, это довольно бессмысленно. :-) Конечно, правильный ответ в этом случае состоит не в том, чтобы преобразовать число с плавающей точкой в ​​шестнадцатеричное, а в том, чтобы использовать представление времени типа INTEGER и преобразовать его в шестнадцатеричную строку. Но все же это можно сделать. :)

1 голос
/ 13 декабря 2010

Вот версия кода на C, сейчас у меня нет времени перенести ее, но, может быть, кто-то другой сможет.

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);
}
...