2011-07-18 57 views
11

Làm cách nào để chuyển đổi chuỗi hex thành int đã ký bằng Python 3.2?Chuỗi ký tự hex để ký int trong Python 3.2?

Điều tốt nhất tôi có thể đưa ra được

h = '9DA92DAB' 
b = bytes(h, 'utf-8') 
ba = binascii.a2b_hex(b) 
print(int.from_bytes(ba, byteorder='big', signed=True)) 

Có cách nào đơn giản hơn? Unsigned trở nên dễ dàng hơn nhiều: int (h, 16)

BTW, nguồn gốc của vấn đề là itunes persistent id - music library xml version and iTunes hex version

+0

Hai dòng b = và ba = có thể được thay thế bằng ba = bytes.fromhex (h). Xem bình luận của Lennart dưới đây. – foosion

Trả lời

17
x = int(h,16) 
if x > 0x7FFFFFFF: 
    x -= 0x100000000 
+0

Tôi tin rằng mệnh đề if cần x = -x ở cuối – foosion

+2

Phải, tôi ghét nhập mã trên iPad. Không thể chạy nó để kiểm tra lại. –

+0

Nhớ điều này mà không cần chạy nó (hoặc có kỹ năng google tốt hơn tôi) là tốt – foosion

4
import struct 

Đối với Python 3 (với sự giúp đỡ ý kiến):

h = '9DA92DAB' 
struct.unpack('>i', bytes.fromhex(h)) 

Đối với Python 2:

h = '9DA92DAB' 
struct.unpack('>i', h.decode('hex')) 

hoặc nếu nó là little endian:

h = '9DA92DAB' 
struct.unpack('<i', h.decode('hex')) 
+0

Hoạt động ở trăn 2.7, nhưng không phải 3.2: AttributeError: đối tượng 'str' không có thuộc tính 'decode' – foosion

+1

Không có Python 3 để kiểm tra trên, nhưng dựa trên tài liệu 'struct.unpack ('> i', byte ('9DA92DAB', 'utf-8'))' nên hoạt động. – kichik

+2

Không. h.decode ('hex') và byte (h, 'utf8') làm những việc hoàn toàn khác nhau. Bạn muốn byte.fromhex (h). –

1

Dưới đây là một chức năng chung, bạn có thể sử dụng cho hex của bất kỳ kích thước:

import math 

# hex string to signed integer 
def htosi(val): 
    uintval = int(val,16) 
    bits = 4 * (len(val) - 2) 
    if uintval >= math.pow(2,bits-1): 
     uintval = int(0 - (math.pow(2,bits) - uintval)) 
    return uintval 

Và để sử dụng nó:

h = str(hex(-5)) 
h2 = str(hex(-13589)) 
x = htosi(h) 
x2 = htosi(h2) 
0

này làm việc cho 16 bit ký ints, bạn có thể mở rộng cho ints 32 bit. Nó sử dụng định nghĩa cơ bản của 2's complement signed numbers. Cũng lưu ý xor với 1 giống với từ khóa nhị phân.

# convert to unsigned 
x = int('ffbf', 16) # example (-65) 
# check sign bit 
if (x & 0x8000) == 0x8000: 
    # if set, invert and add one to get the negative value, then add the negative sign 
    x = -((x^0xffff) + 1) 
0

Đây là một câu trả lời rất muộn, nhưng đây là một chức năng để làm việc trên. Điều này sẽ mở rộng cho bất kỳ chiều dài bạn cung cấp. Tín dụng cho các phần này để một câu trả lời SO (tôi bị mất liên kết, vì vậy xin vui lòng cung cấp nó nếu bạn tìm thấy nó).

def hex_to_signed(source): 
    """Convert a string hex value to a signed hexidecimal value. 

    This assumes that source is the proper length, and the sign bit 
    is the first bit in the first byte of the correct length. 

    hex_to_signed("F") should return -1. 
    hex_to_signed("0F") should return 15. 
    """ 
    if not isinstance(source, str): 
     raise ValueError("string type required") 
    if 0 == len(source): 
     raise valueError("string is empty") 
    sign_bit_mask = 1 << (len(source)*4-1) 
    other_bits_mask = sign_bit_mask - 1 
    value = int(source, 16) 
    return -(value & sign_bit_mask) | (value & other_bits_mask) 
Các vấn đề liên quan