2010-04-06 9 views
3

Quatre octets consécutifs dans une chaîne d'octets indiquent ensemble une valeur. Cependant, seulement 7 bits dans chaque octet sont utilisés; le bit le plus significatif est toujours zéro et donc il est ignoré (cela fait 28 bits au total). Alors ...Utilisation d'octets et de données binaires dans Python

b"\x00\x00\x02\x01" 

serait 000 0000000 0000000 0010000 0001.

Ou, par souci de lisibilité, 10 000 0001. C'est la valeur que représentent les quatre octets. Mais je veux une décimale, donc je le fais:

>>> 0b100000001 
257 

je peux travailler tout ce que moi-même, mais comment pourrais-je intégrer dans un programme?

Répondre

8

Utilisation et plus opérateurs de bits:

bytes = b"\x00\x00\x02\x01" 
i = 0 
for b in bytes: 
    i <<= 7 
    i += b  # Or use (b & 0x7f) if the last bit might not be zero. 
print(i) 

Résultat:

257 
+1

Le 8 bit doit être ignoré, il devrait donc être i + = (b & 0x7f) – miara

+0

@miara: Merci, vous avez raison. Je supposais que c'était zéro. –

+0

En fait, c'est zéro. Votre réponse inédite était juste. Je vais éditer ma question. –

1

Utilisation du bitarray module, vous pouvez le faire beaucoup plus rapidement pour les grands nombres:

Repères (facteur 2.4x speedup !):

[email protected] /tmp % python3 -m timeit -s "import tst" "tst.tst(10000)" 
10 loops, best of 3: 251 msec per loop 
[email protected] /tmp % python3 -m timeit -s "import tst" "tst.tst(100)" 
1000 loops, best of 3: 700 usec per loop 
[email protected] /tmp % python3 -m timeit -s "import sevenbittoint, os" "sevenbittoint.sevenbittoint(os.urandom(10000))" 
10 loops, best of 3: 73.7 msec per loop 
[email protected] /tmp % python3 -m timeit -s "import quick, os" "quick.quick(os.urandom(10000))"       
10 loops, best of 3: 179 msec per loop 

quick.py (de Mark Byers):

def quick(bites): 
    i = 0 
    for b in bites: 
    i <<= 7 
    i += (b & 0x7f) 
    #i += b 
    return i 

sevenbittoint.py:

import bitarray 
import functools 

def inttobitarray(x): 
    a = bitarray.bitarray() 
    a.frombytes(x.to_bytes(1,'big')) 
    return a 

def concatter(accumulator,thisitem): 
    thisitem.pop(0) 
    for i in thisitem.tolist(): 
    accumulator.append(i) 
    return accumulator 

def sevenbittoint(bajts): 
    concatted = functools.reduce(concatter, map(inttobitarray, bajts), bitarray.bitarray()) 
    missingbits = 8 - len(concatted) % 8 
    for i in range(missingbits): concatted.insert(0,0) # zeropad 
    return int.from_bytes(concatted.tobytes(), byteorder='big') 

def tst(): 
    num = 32768 
    print(bin(num)) 
    print(sevenbittoint(num.to_bytes(2,'big'))) 

if __name__ == "__main__": 
    tst() 

tst.py:

import os 
import quick 
import sevenbittoint 

def tst(sz): 
    bajts = os.urandom(sz) 
    #for i in range(pow(2,16)): 
    # if i % pow(2,12) == 0: print(i) 
    # bajts = i.to_bytes(2, 'big') 
    a = quick.quick(bajts) 
    b = sevenbittoint.sevenbittoint(bajts) 
    if a != b: raise Exception((i, bin(int.from_bytes(bajts,'big')), a, b))