在不同的基础上对非常大的数字执行操作的最快方法

2024-10-01 07:10:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我收到一个基于2^k的非常大的数字列表(k<;=30,数字量<;=10^7)。你知道吗

我需要做的是得到两个数字(我们称它们为X和Y),减去它们(A=X-Y,B=Y-X),然后返回A和B的二进制表示

我当前的代码如下所示:

k = int(input())
base = pow(2, k)
numbersX = stdin.readline().split()
digitsX = len(numbersA) - 1

x = 0
i = 1
while i <= digitsX:
    factor = pow(base, digitsX - i)
    x += int(numbersX[i]) * factor
    i += 1

(与Y类似)

我只是简单地把接收到的数字转换成小数,然后减法得到二进制表示。它能工作,但速度很慢。你能建议其他解决办法吗?你知道吗

Sample input:
4 (for k)
6 15
2 7
So X = 6 15 = 6*16^1 + 15*16^0 = 96 + 15 = 111 (decimal)
Y = 2 7 = 2*16^1 + 7*16^0 = 32 + 7 = 39 (decimal)
A = X – Y = 111 – 39 = 72
B = Y – X = 39 – 111 = -72
Output:
01001000 (A in SM binary)
10111000 (B in U2 binary)

Tags: 代码inlt列表inputbase二进制数字
2条回答

这是一种将任意基中的数字转换为整数的方法:

def to_int(digits, base=1024):
    place = 1
    ret = 0
    for digit in reversed(digits):
        ret += place*digit
        place *= base
    return ret

如果你的基数总是2的幂(2^10 = 1024),你也可以这样做(可能效率更高):

def to_int2(digits, log2base=10):
    ret = 0
    for digit in digits:
        ret <<= log2base
        ret += digit
    return ret

要将其表示为二进制字符串,可以执行以下操作:

print('{:0b}'.format(to_int(digits=(981, 5, 0, 1001))))
print('{:0b}'.format(to_int2(digits=(981, 5, 0, 1001))))

两者的结果是相同的(我假设最左边的是最重要的‘数字’;否则您必须reverse‘数字’的顺序):

1111010101000000010100000000001111101001

(读取输入和减法应该是直截了当的。)


对于您添加的示例,其工作方式如下:

x = to_int2(digits=(6, 15), log2base=4)
y = to_int2(digits=(2, 7), log2base=4)

print(x, y) # 111 39
diff = x-y
print('{:08b}'.format(diff))         # 01001000
print('{:08b}'.format(-diff & 0xff)) # 10110111

如果需要动态获取格式和掩码,可以尝试以下操作:

d = 111-39
bit_length = max(int.bit_length(d), int.bit_length(-d))
fmt = '{{:0{}b}}'.format(bit_length+1)
mask = (1<<bit_length+1) - 1
print(fmt.format(d))
print(fmt.format(-d & mask))

不确定是否覆盖了所有的边缘情况。。。但我相信你会从那里得到它!你知道吗

你可以消除pow

x = 0
i = 1
while i <= digitsX:
    x *= base
    x += int(numbersX[i])
    i += 1

相关问题 更多 >