你有一个表示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)
这不是一个家庭作业问题。更新我的算法技巧进行面试。
答案 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位字n
,x
,y
表示128位数字z
和w
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)