提取ASCII整数的前32位

时间:2011-07-16 12:38:15

标签: algorithm bit-manipulation biginteger binary-data

你有一个表示128位无符号整数n的ASCII字符串,即0< = n< 2 ^ 128。

给出一个算法来提取n的二进制表示的最重要的32位,并将它们作为它们编码的无符号32位整数返回。

执行此操作的快速方法是什么,即比实施自己的大数字除法和模2操作更好的方法。 假设一台32bit的机器,i。即你没有64位内置类型。

实施例: 为简洁起见,我们取4位整数并提取前2位:

2(0010) - > 0(00)  7(0111) - > 1(01)  8(1000) - > 2(10) 13(1101) - > 3(11)

这不是一个家庭作业问题。更新我的算法技巧进行面试。

1 个答案:

答案 0 :(得分:1)

我没有看到比简单模拟(有限形式)128位算术更有效的方法。

假设我们有一个函数mul10add(a, b),它计算10*a + b并返回答案的低32位和进位值。如果我们有64位算术,它可以实现为(伪代码):

(word32, word32) mul10add(word32 a, word32 b):
    word64 result = 10*a + b
    word32 carry  = result >> 32
    return (result, carry)

现在,我们采用正常的十进制到二进制算法,并用四个32位字nxy表示128位数字zw n = x*2^96 + y*2^64 + z*2^32 + w。然后,我们可以将调用链接到mul10add,以执行相当于n = 10*n + digitToInt(decimal[i])

word32 high32bits(string decimal):
    word32 x = 0, y = 0, z = 0, w = 0

    # carry
    word32 c = 0

    for i in 0..length(decimal)-1
       (w, c) = mul10add(w, digitToInt(decimal[i]))
       (z, c) = mul10add(z, c)
       (y, c) = mul10add(y, c)
       (x, _) = mul10add(x, c)

    return x

然而,实际上我们并不需要64位架构来实现mul10add。在x86上,我们有mul指令,它将两个32位数相乘得到一个64位数,其中高位32位存储在edx中,低位存储在eax中。还有adc指令,它添加了两个数字,但包括前一个add的进位。所以,在伪装配中:

(word32, word32) mul10add(word32 a, word32 b):
    word32 result, carry
    asm:
        mov a, %eax
        mul 10
        add b, %eax
        adc 0, %edx
        mov %eax, result
        mov %edx, carry
    return (result, carry)