在python中,将原始二进制数据转换为自定义基的最佳方法是什么?
在处理之前,我需要将一些数据转换为base 29,我使用的是:在python中,将原始二进制数据转换为自定义基的最佳方法是什么?,python,binary,int,base,Python,Binary,Int,Base,在处理之前,我需要将一些数据转换为base 29,我使用的是: import string def datatobase(data, base): digs = string.digits + string.lowercase + string.uppercase if base > len(digs): return None digits = [] x = int(data.encode("hex"), 16) while x:
import string
def datatobase(data, base):
digs = string.digits + string.lowercase + string.uppercase
if base > len(digs):
return None
digits = []
x = int(data.encode("hex"), 16)
while x:
digits.append(digs[x % base])
x /= base
digits.reverse()
return ''.join(digits)
问题是,这段小代码使我的程序太慢了,所以您会如何替换它
一个自定义的答案,只有基地29将是伟大的 Base 29,仅用于
int
参数的解决方案
递归:
s = '0123456789ABCDEFGHIJKLMNOPQRS'
def foo(n, s=s):
if n < 29:
return s[n]
a, b = divmod(n, 29)
return foo(a) + s[b]
如果你负责运行时。。。这个版本比你的快2.8倍,比@wwii快7%
def bin2base29(n):
s = '0123456789ABCDEFGHIJKLMNOPQRS'
return s[n] if n < 29 else bin2base29(n / 29) + s[n % 29]
如果您不反对使用第三方软件包,
numpy.base_repr()
是一种非常方便的转换方式:
import os
import numpy
def datatobase(data, base):
n = int(data.encode('hex'), 16)
return numpy.base_repr(n, base)
>>> data = os.urandom(32)
>>> data
'\xfcBs\x82\xa8&\x18\xaaK\x8c$\x0fZ\x95\xc0aA%\x93\x91\xcc\x8a\xa8\xfdbk\xeb\x14\x15\x06\xbag'
>>> datatobase(data, 29)
'A8FB42CHLNEIOOE75AG773EKGBA69QP89PANAF8ROH2GA1LF3CC5H'
>>> datatobase(data, 16)
'FC427382A82618AA4B8C240F5A95C06141259391CC8AA8FD626BEB141506BA67'
您需要进行配置,以查看这是否为您的应用程序提供了足够的性能
更新
分析表明
numpy.base_repr()
比OP的实现慢。这是因为numpy实现基本上与Python中实现的算法相同,并添加了可选的零填充。这不是与OP的基本相同的算法吗?@Anton-但是,基本相同,这个答案包括OP算法没有的一些错误:)1)以29为基数的符号范围为0-9
和A-s
,2)以29为基数的单个“数字”的最大十进制值是28,而不是29。@Anton I将OP的问题视为性能问题-我试图提高性能,但没有进行比较。Bugs fixed,Thnx我认为这是的重复。如果你想快速完成这项工作,比如线性时间,那么我认为你需要将目标基数更改为2的幂,比如32或16。请给出一个你试图转换的数据的示例。我不认为这是一个重复的问题,我已经阅读了页面bitsplit:在发布前指向,但这里我有一个真正的性能问题:)Antom wwii:我正在转换的数据并不重要,我还使用2的幂制作了我的脚本的早期版本(是的,这显然要快得多)。我现在真的需要使用base 29转换。s
太短-它缺少s
。另外,以29为基数的一位数的最大值是28,而不是29。@mhawke谢谢你说得对。我的例子都成功了,现在用28,29试一下……)您是如何衡量算法的性能的?它不比OP快29倍(此外,“29”似乎有点巧合!)@mhawke谢谢你的坚韧。我想我在时间上混合了重复或者习惯了很少的重复。我纠正了它,现在对我来说也更现实了。你有类似的数字吗?事实上,我发现OP是最快的。你的、我的和第二次世界大战的迭代都非常相似。谢谢,我想编辑我的问题,因为这就是我现在正在做的。我很快就会去看它是否真的更好。它比迭代法差40%。@wenzul:二进制字符串的长度对计时有很大影响。在短字符串上,迭代算法要快得多,而在长字符串(例如256字节)上,迭代算法实际上要慢得多。我发现OP的算法在大多数情况下是最快的。还有一件事,您可能没有包括从二进制数据字符串转换为int的成本-这在短字符串上大约值7%?
def bin2base29(n):
s = '0123456789ABCDEFGHIJKLMNOPQRS'
x = ''
while n > 0:
x = s[n % 29] + x
n /= 29
return x
import os
import numpy
def datatobase(data, base):
n = int(data.encode('hex'), 16)
return numpy.base_repr(n, base)
>>> data = os.urandom(32)
>>> data
'\xfcBs\x82\xa8&\x18\xaaK\x8c$\x0fZ\x95\xc0aA%\x93\x91\xcc\x8a\xa8\xfdbk\xeb\x14\x15\x06\xbag'
>>> datatobase(data, 29)
'A8FB42CHLNEIOOE75AG773EKGBA69QP89PANAF8ROH2GA1LF3CC5H'
>>> datatobase(data, 16)
'FC427382A82618AA4B8C240F5A95C06141259391CC8AA8FD626BEB141506BA67'