2010-06-26 135 views
4

我必须将一个给定的16位整数转换为两个8位整数,然后将它们作为输出使用,它们的头部需要两个8位整数,将它们重新组合为16位输入(不幸的是我无法控制)。我的解决方案有效,但感觉不干净。对于粗略的数字我移位原始数字,对于罚款数字,我看着它以256为模。在python中将16位int分成两个8位整数

所以我应该为粗数字进行底板划分,还是应该取最低的8位罚款的数字(如果是这样怎么样?)?

还是我疯了,使用两种不同的方法来拆分数量不是问题?

def convert(x): 
    ''' convert 16 bit int x into two 8 bit ints, coarse and fine. 

    ''' 
    c = x >> 8 # The value of x shifted 8 bits to the right, creating coarse. 
    f = x % 256 # The remainder of x/256, creating fine. 
    return c, f 
+3

只是'返回divmod(x,256)'? – 2010-06-26 09:35:17

+0

我去了: c = x >> 8 f = x&0xff#我以前不知道。 这似乎更真实的是我在做什么,然后divmod或%和/,可能也更接近在另一端执行相同的操作来重新组合它们(我希望)。 – nrn 2010-06-26 09:59:18

回答

9

我会做

c = (x >> 8) & 0xff 
f = x & 0xff 

这是 “安全” 的,例如见

>>> (10303 >> 8) &0xff 
40 
>>> (1030333333 >> 8) &0xff 
163 
>>> (1030333333 >> 8) 
4024739 

因为在Python中,你不能“控制研究”,如果数字是不是还是16位,你要“逼”成一个在最16位值;如果你肯定有一个16位值,那么不需要,但这种方式的func更通用,并且无论“容器”包含什么,只允许你在“16位”中真正“感兴趣”。

+0

阅读“由于在Python中你不能”控制“如果数字是或不是16位”添加_afaik_和解释它说没有一个固定的位宽容器(如uint16所以说)在Python中,_afaik_ – ShinTakezou 2010-06-26 09:39:43

+0

我应该提到,如果x> 16位的东西已经变得非常不可靠,所以如果在路上c> 255,它会引发错误。 – nrn 2010-06-26 09:46:47

+0

你可以放弃c> 255的检查,或保留它们,不要和结果;如果“设计”不能超过65535,则可以删除&和c> 255的检查;但我仍然使用&代替%(在我的答案中编辑,因为在复制粘贴后忘记了更改),正如其他人所说的那样。 – ShinTakezou 2010-06-26 09:53:12

0

如果您使用在不同的地方数的两半,我建议有两个单独的功能,但如果你要在同一个地方使用它们,一个功能将工作一样好。

有几种正确的方法来拆分数字,所以最终都归结为个人偏好。 只要您传递的数字长度至多为16位,您的代码就可以正常工作。 (这可能不会有太大的问题,但你应该知道它)

+0

如果您将单个运算符的应用程序分解出来,那么在这种情况下,您应该有特定的原因来执行此操作,否则您不明白将因素分解的原因。你发明的函数名称可能不像一个阅读你的代码的人应该知道的标准操作符那么清晰,当然你必须去查找函数定义来找出它的真正含义。过分的因式分解,将复杂性转移到通话图中,在我看来是代替意大利面的现代化。 – Steve314 2010-06-26 09:42:42

0

我会使用按位&而不是%。对于短整数而言,这可能几乎没有什么区别,但从更广泛的角度来看,运营商可能更有效率。

有关%如何处理负数的问题可能存在一些问题,但我怀疑这与此处相关。

2

如果操作的目的是算术,则应该保持一致,如果仅用于原始位操作,则使用模数和除法,使用shift和mask。

7

在Python中,位摆弄没有任何特别的优势,所以我会去:

c, f= divmod(your_number, 256) 

编辑:为了让你的意图更加明显的挑战的权力 - 的 - 两个源查看器(如果存在这样的野兽),则可以用更加丰富多彩的替代品替换纯色256,如1<<8,2**8,0x1000400。由2.5的窥孔优化器完成的不断折叠确保它们中的任何一个与使用256(我明显在谈论前两种替代方案,即表达式评估为256;后两个常数256)。

$ python 
Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15) 
[GCC 4.4.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dis 
>>> dis.dis(compile("c, f= divmod(your_number, 1<<8)", "", "exec")) 
    1   0 LOAD_NAME    0 (divmod) 
       3 LOAD_NAME    1 (your_number) 
       6 LOAD_CONST    3 (256) 
       9 CALL_FUNCTION   2 
      12 UNPACK_SEQUENCE   2 
      15 STORE_NAME    2 (c) 
      18 STORE_NAME    3 (f) 
      21 LOAD_CONST    2 (None) 
      24 RETURN_VALUE 
+1

或甚至更好'c,f = divmod(your_number,1 << 8)'清楚地表明你正在分裂在第八位:-) – fortran 2010-06-28 13:19:07

+1

@fortran:当然:)我记得一个程序员问的笑话从一位程序员那里获得1000美元的贷款,他回复道:“为什么我们不把贷款加到1024美元?” – tzot 2010-06-28 15:32:44

+0

ROFL!那很棒! :-D – fortran 2010-06-28 15:43:02

1

你说你正在使用这些数字作为输出,这表明他们会在某个时候的路线被转换成字符串。考虑到这一点,我建议你看看struct module,这是专门为这种事情设计的(将数字打包成二进制数据字符串)。作为奖励,你可以在x大于65535的情况下进行内置错误检查(这样如果程序中有些东西可怕,你会得到一个异常)。例如,

s = struct.pack('>H', x) 

if x > 65535: 
    raise struct.error(...) 
c, f = convert(x) 
s = chr(c) + chr(f) # big-endian (network) byte ordering 

相当于如果需要其他的字节顺序,你可以写

s = struct.pack('<H', x) 

如果你有一大堆的数字在转换的一次,struct.pack可以做一束:

x = [10333, 10475, 3021, ...] # for example 
s = struct.pack('>' + 'H' * len(x), *x) 
相关问题