2

主要问题:多少位数?

让我解释。我有一个二进制数:11000000,十进制数是 192。

转换为十进制后,它将有多少位(以十进制表示)?在我的示例中,它是 3 位数字。但是,这不是问题。我在互联网上搜索并找到了一种用于整数部分的算法和一种用于小数部分的算法。我不太了解它们,但(我认为)它们有效。

当从二进制转换为八进制时,它更容易:每 3 位给你 1 个八进制数字。十六进制相同:每个 4 位 = 1 个十六进制数字。

但是,我很好奇,如果我有一个 P 数字系统的数字并想将它转换为 Q 数字系统,该怎么办?我知道怎么做(我想,我知道 :)),但是,首先,我想知道 Q 系统中需要多少位数(你不,我必须预先分配空间)。

4

7 回答 7

6

以 b 为底写n需要上限(log base b (n)) 个数字

您注意到的比率(八进制/二进制)是log base 8 (n) / log base 2 (n) = 3

(根据记忆,它会坚持吗?)

于 2009-06-07T17:05:42.980 回答
5

如果你有一个以 B 为底的 X 位长的数字,那么可以表示的最大值是 B^X - 1。所以如果你想知道它在 C 底下可能需要多少位,那么你必须找到数字 Y 表示 C^Y - 1 至少与 B^X - 1 一样大。这样做的方法是取 B^X-1 的以 C 为底的对数。由于以 C 为底数的对数 (log) 与该数的自然对数 (ln) 除以 C 的自然对数相同,因此变为:

Y = ln((B^X)-1) / ln(C) + 1

并且由于 ln(B^X) 是 X * ln(B),并且计算起来可能比 ln(B^X-1) 更快并且足够接近正确答案,因此将其重写为

Y = X * ln(B) / ln(C) + 1

将其转换为您最喜欢的语言。因为我们删除了“-1”,所以在某些情况下,我们最终可能会比您需要的多一位数。但更好的是,您可以预先计算 ln(B)/ln(C) 并将其乘以新的“X”和您尝试转换的数字的长度。

于 2009-06-07T17:09:20.107 回答
5

我之前的回答有一个错误:看看 Ben Schwehn 的评论。对不起,我发现并解释了我在下面的上一个答案中犯的错误。

请使用 Paul Tomblin 提供的答案。(改写为使用 P、Q 和 n)

Y = ln(P^n) / ln(Q)
Y = n * ln(P) / ln(Q)

所以 Y(向上取整)是您在系统 Q 中需要的字符数,以表示您可以在系统 P 中用 n 个字符编码的最高数。

我没有答案(这不会转换数字并在临时变量中占用那么多空间)以获得给定数字 1000(bin) = 8(dec) 的最低限度,而您将使用保留 2 个小数位这个公式。

如果临时内存使用不是问题,您可能会作弊并使用(Python):

len(str(int(otherBaseStr,P)))

这将为您提供将基数 P 中的数字转换为字符串 (otherBaseStr) 所需的小数位数。


错误答案:

如果您在 P 数字系统中有一个长度为 n 的数字,那么您可以计算 n 个字符中可能的最大数字:

P^(n-1)

要在数系 Q 中表达这个最高数,您需要使用对数(因为它们是幂的倒数):

log((P^(n-1))/log(Q)
(n-1)*log(P) / log(Q)

例如二进制的 11000000 是 8 个字符。要获得十进制,您需要:

(8-1)*log(2) / log(10) = 2.1 digits (round up to 3)

错误的原因

n 个字符中可能出现的最大数字是

(P^n) - 1

不是

P^(n-1)
于 2009-06-07T17:23:46.220 回答
1

可以使用其他答案给出的公式来计算位数,但是,首先分配最大大小的缓冲区然后返回该缓冲区的相关部分而不是计算对数实际上可能更快。

请注意,缓冲区大小的最坏情况发生在转换为二进制时,这为 32 位整数提供了 32 个字符的缓冲区大小。

可以使用下面的 C# 函数将数字转换为任意基数(代码在 C 或 Java 等其他语言中看起来非常相似):

public static string IntToString(int value, char[] baseChars)
{
    // 32 is the worst cast buffer size for base 2 and int.MaxValue
    int i = 32;
    char[] buffer = new char[i];
    int targetBase= baseChars.Length;

    do
    {
        buffer[--i] = baseChars[value % targetBase];
        value = value / targetBase;
    }
    while (value > 0);

    char[] result = new char[32 - i];
    Array.Copy(buffer, i, result, 0, 32 - i);

    return new string(result);
}
于 2009-06-07T17:19:23.103 回答
0

这里的关键字是“对数”,这里有一些提示性链接:

http://www.adug.org.au/MathsCorner/MathsCornerLogs2.htm

http://staff.spd.dcu.ie/johnbcos/download/Fermat%20material/Fermat_Record_Number/HOW_MANY.html

于 2009-06-07T17:05:34.463 回答
0

查看以 P 和 Q 为底的对数。向下舍入到最接近的整数。

可以使用您喜欢的底数(10 或 e)计算对数底数 P:log_P(x) = log_10(x)/log_10(P)

于 2009-06-07T17:06:38.643 回答
0

您需要单独计算小数部分的长度。

对于二进制到十进制,十进制位数与位数一样多。例如,二进制 0.11001101001001 是十进制 0.80133056640625,都是小数点后的 14 位数字。

对于十进制到二进制,有两种情况。如果小数部分是dyadic,那么位数与十进制数字一样多(与上面的二进制到十进制相同)。如果分数不是二元的,那么位数是无限的。

(你可以使用我的十进制/二进制转换器来做实验。)

于 2009-06-08T00:17:18.943 回答