2017-06-29 67 views
0

我需要將一個字符串表示爲一個數字,但它的長度爲8928313個字符,請注意,該字符串可以包含多個字母,而且我必須能夠有效地將其轉換回來。我目前的(太慢)代碼如下所示:如何將一個字符串表示爲一個數字?

alpha = 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ,[email protected]()+-=[]/*1234567890^*{}\'"$\\&#;|%<>:`~_' 
alphaLeng = len(alpha) 
def letterNumber(letters): 
    letters = str(letters) 
    cof = 1 
    nr = 0 
    for i in range(len(letters)): 
     nr += cof*alpha.find(letters[i]) 
     cof *= alphaLeng 
     print(i,'  ',len(letters)) 
    return str(nr) 
+0

請注意,此代碼工作正常,太慢了 –

+2

我嚴重質疑爲什麼你需要一個約8 MB的精度的數字。最終,一個字符串和一個數字都是字節。一個字符串是你想要的數據類型。 –

+0

你使用Python 3還是Python 2?你沒有使用*我假設? –

回答

1

如果只有ANSII字符。您可以使用ord()chr()

built-in functions

+0

'ord'和'chr'適用於所有角色。但除此之外,我相信這是最合理的答案。 –

+0

對於python 3,這些函數適用於所有Unicode字符。但是python 2只支持ANSII。 – lwshang

+0

沒有。他們只需要使用'unicode'對象。 –

0

有幾種優化可以執行。例如,find方法需要在字符串中搜索相應的字母。字典會更快。甚至更快可能是(基準!)chr函數(如果你對信函排序不太挑剔)和ord函數來顛倒chr。但是,如果你對訂購沒有挑剔,如果你不需要以任何特定格式顯示值,那麼你可能會更好,如果你留下了NULL填充你的字符串並將它視爲內存中的大二進制數。

您可能會通過遍歷字符而不是字符索引來加速。如果您使用的是Python 2,則由於需要生成列表(因爲需要使用xrange代替Python 2),所以較大的range會比較慢。 Python 3使用了一個生成器,所以它更好。

你的print功能會減慢輸出一個公平的位,特別是如果你輸出到tty。

一個巨大的數字圖書館還可以買你的速度向上:Handling big numbers in code

+0

謝謝,我會嘗試做字典。該打印僅用於調試目的,並將很快被刪除。並且使用Python 3.6,可以進行其他優化嗎? –

0

alpha.find()功能需要通過alpha在每次循環迭代。

你或許可以通過使用dict加快速度,因爲詞典的查找O(1):

alpha = 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ,[email protected]()+-=[]/*1234567890^*{}\'"$\\&#;|%<>:`~_' 

alpha_dict = { letter: index for index, letter in enumerate(alpha)} 
print(alpha.find('$')) 
# 83 
print(alpha_dict['$']) 
# 83 
2

好了,因爲其他人都給予可怕的答案,我要一步

  1. 你不應該這樣做。
  2. 你不應該這樣做。
  3. 一個整數和一個字符數組最終是一樣的東西:字節。您可以用相同的方式訪問這些值。
  4. 大多數數字表示限制在8個字節(64位)。您正在查看8 MB,即最大整數表示的100萬次。你不應該這樣做。真。
  5. 你不應該這樣做。你的號碼將是一個自定義的,巨大的數字類型,將在引擎蓋下相同。
  6. 如果你真的想要做到這一點,儘管以上所有原因,這裏是如何...

代碼

def lshift(a, b): 
    # bitwise left shift 8 
    return (a << (8 * b)) 

def string_to_int(data): 
    sum_ = 0 
    r = range(len(data)-1, -1, -1) 
    for a, b in zip(bytearray(data), r): 
     sum_ += lshift(a, b) 
    return sum_; 

不這樣做

說明

人物基本上字節:他們可以以不同的方式進行編碼,但最終你可以把它們在一個給定的編碼中作爲一個字節序列。爲了將它們轉換爲數字,我們可以將它們左移8位,以獲得它們在序列中的位置,從而創建唯一的數字。 r,範圍值,是相反順序的位置:第4個元素需要向左走24個字節(3 * 8)等。

獲得範圍並將我們的數據轉換爲8位整數後,我們可以然後轉換數據並拿出總和,給我們我們唯一的標識符。它與原始數字的字節順序(或反向字節順序)相同,但只是「作爲一個數字」。這完全是徒勞的。不要這樣做。

性能

任何性能是要由你創造沒有正當理由的相同目標,但這個解決方案是體面高性能的事實所超越。

1,000個元素需要〜486微秒,10,000個元素需要〜20.5 ms,而100,000個元素需要約1.5秒。它會工作,但你不應該這樣做。這意味着它被縮放爲O(n ** 2),這可能是由於每次整數大小變大時重新分配數據的內存開銷。這可能需要大約4小時才能處理所有8e6元素(14365秒,計算出的低階數據爲ax**2+bx+c)。請記住,這是爲了獲得與原始數據相同的字節表示。

無用

記住,有〜1e78到1e82原子在整個宇宙中,目前的估計。這是〜2^275。你的值將能夠代表2^71426504,或者大約260000倍,你需要表示宇宙中的每個原子。你不需要這樣的號碼。你永遠不會會。

+0

「字符本質上是8位整數」,這取決於嗯。他們可能是unicode代碼點。在這種情況下,它們由1-4個字節表示。 –

+0

@ juanpa.arrivillaga可以用8位整數表示,使用UTF-8。我從未指定編碼。爲了這個原因,即使編碼爲UTF-32的代碼點也是一樣的。無論如何,OP的整個想法都很糟糕。 –

+1

是的,我明白了。我只是覺得這個評論有點模糊和誤導。換句話說,它堅持Cish「字符是一個字節」的抽象。我毫不懷疑你理解這些微妙之處,但他們可能不清楚其他人閱讀你的答案。字符編碼僅僅是人們只是通過不完全理解就能擺脫的東西之一。 –

相關問題