【问题标题】:python 2.5: how to convert float to hex?python 2.5:如何将浮点数转换为十六进制?
【发布时间】:2010-12-13 19:02:57
【问题描述】:

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

我发现了大量将十六进制转换为浮点数的示例,但我找不到任何可以让我做 python >= 2.6 的 float.hex() 所做的事情。

【问题讨论】:

  • 如果您说为什么要这样做会有所帮助,例如什么会消耗十六进制字符串?
  • 我需要它来创建一个唯一标识符(连同其他东西)。如果你想知道为什么,答案是:这不是我的选择。
  • 如果您不需要能够从唯一 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


【解决方案1】:

在 2.6 版之前的 Python 中无法移植;它需要 sys.float_info 中的信息,这是 Python 2.6 中的新内容。

如果您想以不可移植的方式执行此操作,即针对您的特定平台,您需要查看用于生成 2.4/5 Python 的 C 编译器的 float.h 文件,或者查看 sys. float_info 由您平台上的 2.6 或 2.7 实现返回(并相信它适用于您的 2.4/5 Python)。然后,您需要查看 Python 源代码 (Objects/floatobject.c) 中的 float_hex 函数并将其转换为 Python 并对其进行测试(可能针对 2.6/7 Python)。

这似乎需要做很多工作,为什么?你的目标是什么?你想做什么repr(your_float)做不到的事情?

编辑:需要唯一标识符

注意 time.time() 不是很精确:

""" 时间.时间() 以浮点数形式返回时间,以自纪元以​​来的秒数表示,以 UTC 为单位。请注意,尽管时间始终以浮点数形式返回,但并非所有系统都提供比 1 秒更好的精度的时间。虽然此函数通常返回非递减值,但如果系统时钟已在两次调用之间调回,则它可以返回比先前调用更低的值。 """

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

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

这样就够了吗?

【讨论】:

    【解决方案2】:

    这里是 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);
    }
    

    【讨论】:

      【解决方案3】:

      当然,它可以以便携的方式完成,这只是数学。以下是方法(包括证明它有效的测试)。

      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)
      

      是的,这毫无意义。 :-) 当然,在这种情况下,正确的答案是不要将浮点数转换为十六进制,而是使用时间的整数表示并将其转换为十六进制字符串。但是,仍然可以做到。 :)

      【讨论】:

        猜你喜欢
        • 2014-03-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-11
        • 1970-01-01
        • 2010-12-08
        • 1970-01-01
        • 2016-06-02
        相关资源
        最近更新 更多