2017-06-29 353 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“字符是一个字节”的抽象。我毫不怀疑你理解这些微妙之处,但他们可能不清楚其他人阅读你的答案。字符编码仅仅是人们只是通过不完全理解就能摆脱的东西之一。 –

相关问题