高效的数制转换算法
当源整数大小任意时,是否有有效的数字系统之间转换的算法?
例如,假设有一个整数数组 {1, 4, 8} 作为十进制格式的 148 作为输入。它可能会转换为十六进制格式的 {9, 4},或八进制格式的 {2, 2, 4},或二进制格式的 {1, 0, 0, 1, 0, 1, 0, 0},或者只是 { 148} 采用 1234 进制格式或其他格式。
当实际值可以用机器支持的字长来表示时,这很简单。但是当它达到任意大小时,我找不到比 O(n^2) 更好的有效方法。
Is there any efficient algorithm for conversion between numeral system when the size of source integer is arbitrary?
For example, assume that there is an integer array {1, 4, 8} which is 148 in decimal format as an input. It might be converted to {9, 4} in hexadecimal format, or {2, 2, 4} in octal, or {1, 0, 0, 1, 0, 1, 0, 0} in binary format, or just {148} in 1234-ary format or something.
It's simple when the actual value can be expressed in word-size supported by machine. But when it goes to arbitrary size, I cannot find efficient way better than O(n^2).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除以底数,推回模块,冲洗并重复,同时商!= 0。
因此,例如将 148 转换为底数 16
因此,十六进制的 148 是 0x94。这不应该花这么长时间。
Divide by the base, push back the module, rinse and repeat while quotient != 0.
So, for example convert 148 in base 16
So, 148 in hex is 0x94. This shouldn't take so long.
假设我们想要从基
b1
转换为基b2
。如果b1
和b2
都是公共基数b
的幂,则说b1 = b^i1
和b2 = b^i2
那么这可以在O(n)
内完成。特别是这适用于二进制、八进制、十六进制、2^32
、2^64
等之间的转换。那是因为您实际上只是对位进行重新分区。考虑八进制和十六进制中数字 3214 的数字位:您可以看到它们都是相同的位,只是在每个基数的数字之间划分不同。制作一种使用位移位和掩码从一种算法转换为另一种算法并不难。从例如基数 9 到基数 27 的转换也是如此,只不过您将基数 3 数字而不是位进行分区,然后将它们转移到不同的存储桶中。
现在,如果
b1
和b2
不相称,那么事情就不那么简单了,但仍然可以使用分而治之的方法在次二次时间内完成。教科书[1]的7.1节描述了基数转换的算法1.25和1.26。这些算法的假设是您正在转换为用于大整数算术的基数(并且您可以在该基数中进行大整数算术)。您可以使用它通过转换b1 ->; 来实现任意基数转换。 bigint -> b2 不过。
在这里,我将在 Python 中演示算法 1.25,它自然支持开箱即用的大整数算术:
因为这首先使用
str
将所有字符转换为int
,所以此实现仅适用于基数从 2 到 10,但如果输入是作为整数列表而不是字符串提供的,则不需要该步骤。请注意,此代码中并未明确说明,但l1 + b*l2
和b**2
需要使用大整数算术进行计算。这里返回的结果是一个大整数。算法1.26可以将一个大整数转换为任意基数的数字字符串。一个简单的实现:
这些算法都具有复杂度
M(n)*log(n)
,其中n
是大整数中的位数,M(n) )
是两个n
位整数相乘的成本。如果大整数乘法和除法具有次二次乘法性能,那么这些算法也将如此。[1] Richard P. Brent 和 Paul Zimmermann,《现代计算机算术》。
https://members.loria.fr/PZimmermann/mca/ mca-cup-0.5.9.pdf
Suppose we want to convert from base
b1
to baseb2
. Ifb1
andb2
are both powers of a common baseb
sayb1 = b^i1
andb2 = b^i2
then this can be done inO(n)
. In particular this applies to say converting between binary, octal, hexadecimal,2^32
,2^64
etc. That's because you're really just repartitioning the bits. Consider the bits of the digits of number 3214 in octal vs hexadecimal:You can see that it's all the same bits just divided differently among the digits in each base. It's not hard to make an algorithm that converts from one to the other using bit-shifts and masks. The same would go for converting from e.g. base 9 to base 27 except that you partition the base 3 digits rather than bits and then shift those into different buckets.
Now if
b1
andb2
are not commensurate then it's not so simple but it can still be done in subquadratic time using divide and conquer approaches. Section 7.1 of the textbook [1] describes algorithms 1.25 and 1.26 for base conversion. The presumption of those algorithms is that you are converting into and out of the base that is used for big integer arithmetic (and that you can do big integer arithmetic in that base). You can use this to implement arbitrary base conversion by convertingb1 -> bigint -> b2
though.Here I'll demonstrate algorithm 1.25 in Python which naturally supports big integer arithmetic out of the box:
Because this first converts all characters to
int
withstr
this implementation will only work for bases from 2 to 10 but had the input been provided as a list of integers rather than a string then that step wouldn't be necessary. Note that it isn't explicit here in this code butl1 + b*l2
andb**2
need to be computed with big integer arithmetic. The result returned here is a big integer.Algorithm 1.26 can convert a big integer to a string of digits in any base. A simple implementation:
These algorithms both have complexity
M(n)*log(n)
wheren
is the number of bits in the big integer andM(n)
is the cost of multiplying twon
bit integers. If the big integer multiplication and division has subquadratic performance for multiplication then these algorithms will as well.[1] Richard P. Brent and Paul Zimmermann, Modern Computer Arithmetic.
https://members.loria.fr/PZimmermann/mca/mca-cup-0.5.9.pdf