添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

python 2.5:如何将浮点数转换为十六进制?

1 人关注

我想用python 2.4/2.5转换一个浮点数( time.time() 的输出)为十六进制。

I found tons of examples that convert hex to float, but I cannot find anything that allows me to do what the float.hex() of python >= 2.6 does.

5 个评论
如果你能说出你为什么要这样做,例如,什么会消耗十六进制的字符串?
我需要它来创建一个独特的标识符(和其他东西一起)。如果你想知道为什么这样,答案是:这不是我的选择。
如果你不需要从唯一的ID中恢复时间,而只是想让不同的时间产生不同的数字,可以尝试用hash(time.time())来获得一个整数,用hex(hash(time.time()))来获得一个 "0xBLAHBLAH "形式的字符串。
@Russell Borogove: aarrgghh hash(x) == hash(y) and x != y 有可能评估为 True ......他希望如此 UNIQUE
如果你想要一个唯一的标识符,只要使用uuid模块( docs.python.org/library/uuid.html )--它是为这个原因而制作的。
python
floating-point
hex
Giovanni Di Milia
Giovanni Di Milia
发布于 2010-12-14
3 个回答
John Machin
John Machin
发布于 2010-12-14
已采纳
0 人赞同

在2.6版之前的Python中,它不能被移植;它需要sys.float_info中的信息,这在Python 2.6中是新的。

如果你想做非移植性的,即为你的特定平台,你需要查看用于产生你的 2.4/5 Python 的 C 编译器的 float.h 文件,或者查看你的平台上由 2.6 或 2.7 实现返回的 sys.float_info (并且相信它适用于你的 2.4/5 Python)。然后你需要查看 Python 源文件 (Objects/floatobject.c) 中的 float_hex 函数,将其翻译成 Python 并进行测试 (也许是针对 2.6/7 Python)。

这似乎是一个很大的工作,为了什么?你的目标是什么?你想做什么,用 repr(your_float) 不能实现的?

Edit :需要一个独特的标识符

请注意,time.time()并不是非常精确。

time.time() 将时间以浮点数的形式返回,以UTC为单位,表示自纪元以来的秒数。请注意,尽管时间总是以浮点数形式返回,但并非所有系统都提供比1秒更精确的时间。虽然这个函数通常返回非递减值,但如果系统时钟在两次调用之间被调回,它可能会返回一个比前一次调用更低的值。

允许高达十亿分之一秒的分辨率。

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

这样就够了吗?

John La Rooy
John La Rooy
发布于 2010-12-14
0 人赞同

这是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");
            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;
        esign = (int)'+';
    if (x < 0.0)
        return PyString_FromFormat("-0x%sp%c%d", s, esign, e);
        return PyString_FromFormat("0x%sp%c%d", s, esign, e);
    
Lennart Regebro
Lennart Regebro
发布于 2010-12-14
0 人赞同

当然,它可以以一种可移植的方式完成,这只是数学问题。下面是如何做到的(包括证明它有效的测试)。

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()