簡體   English   中英

在Python中將二進制列表(或數組)轉換為整數的最快方法

[英]Fastest way to convert a binary list(or array) into an integer in Python

假設有一個包含1和0的列表(或數組)。

gona = [1, 0, 0, 0, 1, 1]

我想將其轉換為由二進制值100011 (由列表中的元素組成的數字)表示的整數。

我知道可以做到以下幾點。

int("".join(map(str, gona)),2)

要么

編輯: int("".join([str(i) for i in gona]),2)

還有其他更快的方法嗎?

這是我最快想到的。 您的初始解決方案略有不同:

digits = ['0', '1']
int("".join([ digits[y] for y in x ]), 2)

%timeit int("".join([digits[y] for y in x]),2)
100000 loops, best of 3: 6.15 us per loop
%timeit int("".join(map(str, x)),2)
100000 loops, best of 3: 7.49 us per loop

(順便說一句,在這種情況下,使用列表理解似乎比使用生成器表達式更快。)

編輯:

另外,我討厭成為一個聰明人,但是您總是可以以內存換取速度:

# one time precalculation
cache_N = 16  # or much bigger?!
cache = {
   tuple(x): int("".join([digits[y] for y in x]),2)
   for x in itertools.product((0,1), repeat=cache_N)
}

然后:

res = cache[tuple(x)]

更快。 當然,這僅在某種程度上是可行的...

編輯2:

現在,我看到您說您的列表包含32個元素。 在這種情況下,緩存解決方案可能是不可行的,但是我們有更多的方法來交換內存速度。 例如,使用cache_N=16 ,這肯定是可行的,您可以訪問兩次:

c = 2 ** cache_N # compute once
xx = tuple(x)
cache[xx[:16]] * c + cache[xx[16:]]

%timeit cache[xx[:16]] * c + cache[xx[16:]]
1000000 loops, best of 3: 1.23 us per loop  # YES!

您可以這樣做:

sum(x << i for i, x in enumerate(reversed(gona)))

雖然不快

我決定創建一個腳本來試用4種執行此任務的方法。

import time

trials = range(1000000)
list1 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0]
list0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
listmix = [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]

def test1(l):
    start = time.time()
    for trial in trials:
        tot = 0
        n = 1
    for i in reversed(l):
            if i:
                tot += 2**n
            n += 1
    print 'Time taken:', str(time.time() - start)

def test2(l):
    start = time.time()
    for trial in trials:
        int("".join(map(str, l)),2)
    print 'Time taken:', str(time.time() - start)

def test3(l):
    start = time.time()
    for trial in trials:
        sum(x << i for i, x in enumerate(reversed(l)))
    print 'Time taken:', str(time.time() - start)

def test4(l):
    start = time.time()
    for trial in trials:
        int("".join([str(i) for i in l]),2)
    print 'Time taken:', str(time.time() - start)


test1(list1)
test2(list1)
test3(list1)
test4(list1)
print '.'
test1(list0)
test2(list0)
test3(list0)
test4(list0)
print '.'
test1(listmix)
test2(listmix)
test3(listmix)
test4(listmix)

我的結果:

Time taken: 7.14670491219
Time taken: 5.4076821804
Time taken: 4.7349550724
Time taken: 7.24234819412
.
Time taken: 2.29213285446
Time taken: 5.38784003258
Time taken: 4.70707392693
Time taken: 7.27936697006
.
Time taken: 4.78960323334
Time taken: 5.36612486839
Time taken: 4.70103287697
Time taken: 7.22436404228

結論:@goncalopp的解決方案可能是最好的解決方案。 它一直都很快。 另一方面,如果您的零可能比零多,那么遍歷列表並手動乘以2的冪並加起來將是最快的。

編輯:我重新編寫了腳本以使用timeit,源代碼位於http://pastebin.com/m6sSmmR6

我的輸出結果:

7.78366303444
2.79321694374
5.29976511002
.
5.72017598152
5.70349907875
5.66881299019
.
5.25683712959
5.17318511009
5.20052909851
.
8.23388290405
8.24193501472
8.15649604797
.
3.94102287292
3.95323395729
3.9201271534

如果全為零,我逐步遍歷列表的方法會向后加2的冪,但是,否則,@ sxh2的方法肯定是最快的,而且我的實現甚至不包括他的緩存優化。

我嘗試了這個:

int(str(gona).replace(', ','')[1:-1])

並與此相比(最快的情況是@ Sohcahtoa82):

sum(x << i for i, x in enumerate(reversed(gona)))

在我的機器上,第一個完成的時間為1000000次,傳輸時間約為5.97秒。 第二種情況需要約8.03s。

我嘗試了另一種方法,並將其插入@ Sohcahtoa82的代碼中:

T61 = """
    l = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
    digits = ['0', '1']
    s = ''
    for y in l:
        s += digits[y]
    int(s, 2)
"""

T60 = """
    l = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    digits = ['0', '1']
    s = ''
    for y in l:
        s += digits[y]
    int(s, 2)
"""

T6mix = """
    l = [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]
    digits = ['0', '1']
    s = ''
    for y in l:
        s += digits[y]
    int(s, 2)
"""

並得到了這些結果。 我的是最后一組時間。

5.45334255339
1.89000112578
4.14859673729
.
4.39018410496
4.21122597336
4.57919181895
.
3.59095765307
3.25353409619
3.78588067833
.
6.53343932548
6.33234985363
6.65685678006
.
2.74509861151
2.6111819044
2.83928911064
.
2.79519545737
2.66091503704
2.9183024407

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM