简体   繁体   English

Python中的位列表为integer

[英]Bits list to integer in Python

I have such list in Python: [1,0,0,0,0,0,0,0] .我在 Python 中有这样的列表: [1,0,0,0,0,0,0,0] Can I convert it to integer like as I've typed 0b10000000 (ie convert to 128)?我可以将它转换为 integer,就像我输入 0b10000000 一样(即转换为 128)吗? I need also to convert sequences like [1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0] to integers (here it will return 0b1100000010000000, ie 259).我还需要将[1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0]之类的序列转换为整数(这里它将返回 0b1100000010000000,即259). Length of list is always a multiple of 8, if it is necessary.如果需要,列表的长度始终是 8 的倍数。

You can use bitshifting: 你可以使用bitshifting:

out = 0
for bit in bitlist:
    out = (out << 1) | bit

This easily beats the "int cast" method proposed by ARS, or the modified cast with lookup proposed by Steven Rumbalski: 这很容易击败ARS提出的“int cast”方法,或Steven Rumbalski提出的修改后的查找:

>>> def intcaststr(bitlist):
...     return int("".join(str(i) for i in bitlist), 2)
... 
>>> def intcastlookup(bitlist):
...     return int(''.join('01'[i] for i in bitlist), 2)
... 
>>> def shifting(bitlist):
...     out = 0
...     for bit in bitlist:
...         out = (out << 1) | bit
...     return out
... 
>>> timeit.timeit('convert([1,0,0,0,0,0,0,0])', 'from __main__ import intcaststr as convert', number=100000)
0.5659139156341553
>>> timeit.timeit('convert([1,0,0,0,0,0,0,0])', 'from __main__ import intcastlookup as convert', number=100000)
0.4642159938812256
>>> timeit.timeit('convert([1,0,0,0,0,0,0,0])', 'from __main__ import shifting as convert', number=100000)
0.1406559944152832

...or using the bitstring module ...或使用bitstring模块

>>> from bitstring import BitArray
>>> bitlist=[1,0,0,0,0,0,0,0]
>>> b = BitArray(bitlist)
>>> b.uint
128

I came across a method that slightly outperforms Martijn Pieters solution, though his solution is prettier of course. 我遇到的方法稍微优于Martijn Pieters解决方案,尽管他的解决方案当然更漂亮。 I am actually a bit surprised by the results, but anyway... 我对结果感到有些惊讶,但无论如何......

import timeit

bit_list = [1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0]

def mult_and_add(bit_list):
    output = 0
    for bit in bit_list:
        output = output * 2 + bit
    return output

def shifting(bitlist):
     out = 0
     for bit in bitlist:
         out = (out << 1) | bit
     return out

n = 1000000

t1 = timeit.timeit('convert(bit_list)', 'from __main__ import mult_and_add as convert, bit_list', number=n)
print "mult and add method time is : {} ".format(t1)
t2 = timeit.timeit('convert(bit_list)', 'from __main__ import shifting as convert, bit_list', number=n)
print "shifting method time is : {} ".format(t2)

Result: 结果:

mult and add method time is : 1.69138722958 
shifting method time is : 1.94066818592 

Try this one-liner: 试试这个单行:

int("".join(str(i) for i in my_list), 2)

If you're concerned with speed/efficiency, take a look at Martijn Pieters' solution. 如果你关注速度/效率,请看看Martijn Pieters的解决方案。

how about this: 这个怎么样:

out = sum([b<<i for i, b in enumerate(my_list)])

or in reverse order: 或者以相反的顺序:

out = sum([b<<i for i, b in enumerate(my_list[::-1])])

The simplest method suggested by @Akavall is the fastest one. @Akavall 建议的最简单的方法是最快的方法。 The additional timing below for mult_add_xor shows that the bit operations are slower in python since simple addition "+ bit" is faster than xor "| bit" and the multiplication by 2 is faster than the bit shift "<< 1".下面的mult_add_xor 的附加时序表明python 中的位操作较慢,因为简单的加法“+ bit”比xor“| bit”快,并且乘以2 比位移“<< 1”快。

import timeit

bit_list = [1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]


def mult_and_add(bit_list):
    output = 0
    for bit in bit_list:
        output = output * 2 + bit
    return output


def mult_and_xor(bit_list):
    output = 0
    for bit in bit_list:
        output = output * 2 | bit
    return output


def shifting(bitlist):
    out = 0
    for bit in bitlist:
        out = (out << 1) | bit
    return out


n = 1000000

a1 = mult_and_add(bit_list)
a2 = mult_and_xor(bit_list)
a3 = shifting(bit_list)

print('a1: ', a1, ' a2: ', a2, ' a3: ', a3)
assert a1 == a2 == a3

t = timeit.timeit('convert(bit_list)',
                  'from __main__ import mult_and_add as convert, bit_list',
                  number=n)
print("mult and add method time is : {} ".format(t))
t = timeit.timeit('convert(bit_list)',
                  'from __main__ import mult_and_xor as convert, bit_list',
                  number=n)
print("mult and xor method time is : {} ".format(t))
t = timeit.timeit('convert(bit_list)',
                  'from __main__ import shifting as convert, bit_list',
                  number=n)
print("shifting method time is : {} ".format(t))

Output:输出:

a1:  49280  a2:  49280  a3:  49280
mult and add method time is : 0.9469406669959426 
mult and xor method time is : 1.0905388034880161 
shifting method time is : 1.2844801126047969 

Fastest one-liner:最快的单线:

def reduced_plus(bitlist):
    return functools.reduce(lambda acc, val: acc * 2 + val, bitlist)

Benchmarking:基准测试:

import timeit
import functools

def shifting_plus(bitlist):
    out = 0
    for bit in bitlist:
        out = out * 2 + bit
    return out

def shifting(bitlist):
    out = 0
    for bit in bitlist:
        out = (out << 1) | bit
    return out

def reduced_plus(bitlist):
    return functools.reduce(lambda acc, val: acc * 2 + val, bitlist)

def reduced(bitlist):
    return functools.reduce(lambda acc, val: acc << 1 | val, bitlist)

def summed(bitlist):
    return sum([b<<i for i, b in enumerate(bitlist)])

def intcastlookup(bitlist):
    return int(''.join('01'[i] for i in bitlist), 2)

cycles = 1_000_000
for fname in ["shifting_plus", "shifting", "reduced_plus", "reduced", "summed", "intcastlookup"]:
    result = timeit.timeit('convert([1,0,0,0,0,0,0,0])', f'from __main__ import {fname} as convert')
    print(f"{result:.3f} s - {fname}")

results:结果:

0.465 s - shifting_plus
0.779 s - shifting
0.807 s - reduced_plus
0.841 s - summed
0.884 s - intcastlookup
1.024 s - reduced

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM