我有任意基数中整数表示的长度。假设长度为 15,基数为 36。然后我想计算出所述整数的表示在另一个任意基数中的长度。即,转换为基数 2 可能会导致长度为 68。
我知道它是按照下面的思路,但我不能完全理解我需要地板和天花板的东西,而且我得到的结果有些离谱:
length * log(fromBase) / log(toBase)
遵循类似 Mathematica 的语法,让
Log[b,n]
表示以 n 为底的 b 的对数。让Log[n]
代表 的自然对数n
。
那么比例
Log[b1,n]/Log[b2,n]
是常数,并且等于
Log[b2]/Log[b1]
这个比率是一个乘数,用于从 base 中的位数计算 baseb1
中的位数b2
(反之亦然,如果你这样看的话)。对于问题中的示例,需要一个 15 位的 base-36 数字
15*Log[36]/Log[2] == 77.5489
基数 2 位。当然,这正是您的问题。您只需要将最终答案四舍五入到下一个整数。
当然,我不确定为什么您似乎得到了一些偏离的结果。
可悲的是,如果不进行高精度计算,就没有精确的解决方案。例如,(我将在工作中使用 MATLAB,包括我自己编写的用于高精度工作的工具)什么是 2^200?在基数 10 中,我们得到:
vpij(2)^200
ans =
1606938044258990275541962092341162602522202993782792835301376
该数字使用以 201 为基数的 2 位数字以二进制形式表示。但是,2^200-1 只需要 200 个以 2 为底的数字即可表示。
vpij(2)^200 - 1
ans =
1606938044258990275541962092341162602522202993782792835301375
现在,我们可以通过只取最高位数字来计算这些数字的对数,作为双精度数。我们需要将一个数字的以 2 为底的对数加 1,以了解表示它所需的以 2 为底的数字的数量。
format long g
1 + log2(vpij(2)^200)
ans =
201
1 + log2(vpij(2)^200 - 1)
ans =
201
这里 log2 正是这样做的,采用最高十进制数字来计算该日志。请注意,它无法判断第二个数字确实需要少一位数字才能以二进制形式存储。
vpij2bin(vpij(2)^200)
ans =
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
vpij2bin(vpij(2)^200 - 1)
ans =
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
我们可以通过对这些数字进行高精度日志来了解会发生什么。因此,精确到小数点后 100 位,
log2(hpf(2,100)^200)
ans =
200
log2(hpf(2,100)^200 - 1)
ans =
199.9999999999999999999999999999999999999999999999999999999999991022086719253476184905817230522465495
这两个数字之间的差异非常小。
log10(hpf(2,100)^200) - log10(hpf(2,100)^200 - 1)
ans =
2.702621195974725251000559400026211938865e-61
因此,任何使用日志的计算都必须在此处失败,除非本身采用高精度日志。充其量,你可以在正确的数字范围内,但仅此而已。因此,如果您的目标只是为数字分配足够的空间,那么总是比明显需要的多分配一位数字。在您开始使用真正巨大的力量之前,这应该足够了。
(VPIJ 是 MATLAB 中的一种新的可变精度整数形式,它将直接取代我的旧 VPI 工具。HPF 已经在文件交换中可用。)
您可以在不使用对数的情况下得到准确的答案。沿着任意基数的基数向上走,直到数字适合里面。
Python 示例:
def count_digits(number, base):
radix = 1
while number >= base ** radix:
radix += 1
return radix