[英]Sneaking unsigned values from Jython, through Java, to C and back again
我參與了一個項目,其中我們將C API(通過Java)綁定到Jython中。 我們遇到了無符號值的問題(因為Java不支持它們)。 我們可以在Java和C之間使用強制轉換,但是從Jython遷移到Java是一項艱巨的任務。
我用Python編寫了一些“廣播”函數。 它們將表示有符號或無符號值的位模式轉換為表示相反符號的SAME BIT PATTERN。
例如:
>>> u2s(0xFFFFFFFF)
-1L
>>> hex(s2u(-1))
'0xffffffffL'
有沒有更優雅的方法來處理Jython與Java之間的這種符號轉換? 有人嘗試過這樣做嗎?
這是整個模塊:
__all__ = ['u2s', 's2u']
def u2s(v,width=32):
"""
Convert a bit pattern representing an unsigned value to the
SAME BIT PATTERN representing a signed value.
>>> u2s(0xFFFFFFFF)
-1L
>>> u2s(0x7FFFFFFF)
2147483647L
"""
msb = int("1" + ((width - 1) * '0'), 2)
msk = int("1" * width, 2)
nv = v & msk
if 0 < (msb & nv):
return -1 * ((nv ^ msk) + 1)
else:
return nv
def s2u(v,width=32):
"""
Convert a bit pattern representing a signed value to the
SAME BIT PATTERN representing an unsinged value.
>>> hex(s2u(-1))
'0xffffffffL'
>>> hex(s2u(1))
'0x1L'
"""
msk = int("1" * width, 2)
if 0 > v:
return msk & (((-1 * v) ^ msk) + 1)
else:
return msk & v
if __name__ == "__main__":
import doctest
doctest.testmod()
我去了,在Jython中對我的代碼VS接受的答案進行了基准測試。 可接受的答案的效果要好大約1/3! 我只測試了具有明確定義的寬度的版本。
使用以下代碼編輯我提供的代碼以自己運行基准測試:
def _u2s(v, width=32):
fmt = {8: "B", 16: "H", 32: "I", 64: "Q"}[width]
return struct.unpack(fmt.lower(), struct.pack(fmt, v))[0]
def _s2u(v, width=32):
fmt = {8: "B", 16: "H", 32: "I", 64: "Q"}[width]
return struct.unpack(fmt, struct.pack(fmt.lower(), v))[0]
if __name__ == "__main__":
import doctest
doctest.testmod()
import time
x = range(-1000000,1000000)
t1 = time.clock()
y = map(s2u, x)
t2 = time.clock()
print t2 - t1
_t1 = time.clock()
z = map(_s2u, x)
_t2 = time.clock()
print _t2 - _t1
struct模塊非常適合
import struct
def u2s(v):
return struct.unpack("i", struct.pack("I", v))[0]
def s2u(v):
return struct.unpack("I", struct.pack("i", v))[0]
支持所有常見寬度
import struct
def u2s(v, width=32):
fmt = {8: "B", 16: "H", 32: "I", 64: "Q"}[width]
return struct.unpack(fmt.lower(), struct.pack(fmt, v))[0]
def s2u(v, width=32):
fmt = {8: "B", 16: "H", 32: "I", 64: "Q"}[width]
return struct.unpack(fmt, struct.pack(fmt.lower(), v))[0]
支持最大64位的任何寬度
import struct
def u2s(v, width=32):
return struct.unpack("q",struct.pack("Q",v<<(64-width)))[0]>>(64-width)
def s2u(v, width=32):
return struct.unpack("Q",struct.pack("q",v<<(64-width)))[0]>>(64-width)
如果您需要支持64位以上的寬度
def u2s(v, width=32):
return v if v < (1L<<(width-1)) else v - (1L<<width)
def s2u(v, width=32):
return v if v >= 0 else v + (1L<<width)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.