我想创建一个函数,其中对于任意整数输入值(让我们说无符号32位)和给定数量的d
数字,返回值将是{{ 1}}数字d
基数,B
是可用于表示B
数字上给定输入的最小基数。
这是一个示例输入 - 输出我想到的3位数字:
d
赋值应为1:1,对于每个输入值,应该只有一个唯一的输出值。可以把它想象成函数应该从奇怪排序的Input Output
0 0 0 0
1 0 0 1
2 0 1 0
3 0 1 1
4 1 0 0
5 1 0 1
6 1 1 0
7 1 1 1
8 0 0 2
9 0 1 2
10 1 0 2
11 1 1 2
12 0 2 0
13 0 2 1
14 1 2 0
15 1 2 1
16 2 0 0
17 2 0 1
18 2 1 0
19 2 1 1
20 0 2 2
21 1 2 2
22 2 0 2
23 2 1 2
24 2 2 0
25 2 2 1
26 2 2 2
27 0 0 3
28 0 1 3
29 1 0 3
30 1 1 3
.. .....
基数列表中返回nth
值。
实际上这是我到目前为止唯一的方法 - 给定输入值,在尽可能小的B
基数中生成所有数字以表示B
位数的输入,然后应用对结果进行自定义排序('惩罚'更高的数字值并将它们放回排序中),并从排序的数组中返回d
值。这可行,但实现效率极低 - 我希望在不生成输入值的所有数字的情况下执行此操作。
实现此功能的有效方法是什么?任何语言或伪代码都可以。
答案 0 :(得分:2)
假设所有值都是正数,那么让我们进行简单的数学计算:
如果
B d > Ñ
所以
B> N 1 / d
因此,计算N 1 / d 值,将其四舍五入(如果为整数则递增),您将获得最小的基数B. (请注意,可能会出现数字错误)
示例:
d=2, N=99 => 9.95 => B=10
d=2, N=100 => 10 => B=11
d=2, N=57 => 7.55 => B=8
d=2, N=33 => 5.74 => B=6
Delphi代码
function GetInSmallestBase(N, d: UInt32): string;
const
Digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
Base, i: Byte;
begin
Base := Ceil(Power(N, 1/d) + 1.0E-12);
if Base > 36 then
Exit('Big number, few digits...');
SetLength(Result, d);
for i := d downto 1 do begin
Result[i] := Digits[1 + N mod Base]; //Delphi string is 1-based
N := N div Base;
end;
Result := Result + Format(' : base [%d]', [Base]);
end;
begin
Memo1.Lines.Add(GetInSmallestBase(99, 2));
Memo1.Lines.Add(GetInSmallestBase(100, 2));
Memo1.Lines.Add(GetInSmallestBase(987, 2));
Memo1.Lines.Add(GetInSmallestBase(1987, 2));
Memo1.Lines.Add(GetInSmallestBase(87654321, 6));
Memo1.Lines.Add(GetInSmallestBase(57, 2));
Memo1.Lines.Add(GetInSmallestBase(33, 2));
99 : base [10]
91 : base [11]
UR : base [32]
Big number, few digits...
H03LL7 : base [22]
71 : base [8]
53 : base [6]
答案 1 :(得分:2)
MBo的答案显示了如何找到代表具有给定位数的整数的最小基数。
我不太确定你的例子中的顺序。我的答案基于不同的排序:创建所有可能的 n - 数字,最多为基数 b (例如,最大基数为10和3位的所有数字最多为999) 。首先根据最大数字对它们进行排序。数字是在具有相同最大数字的组内的正常范围内排序的。这保留了从8到26的所有值必须为3的基本特征,但内部排序不同:
8 0 0 2
9 0 1 2
10 0 2 0
11 0 2 1
12 0 2 2
13 1 0 2
14 1 1 2
15 1 2 0
16 1 2 1
17 1 2 2
18 2 0 0
19 2 0 1
20 2 0 2
21 2 1 0
22 2 1 1
23 2 1 2
24 2 2 0
25 2 2 1
26 2 2 2
当你的基数为2时,生活很简单:只需生成适当的二进制数。
对于其他基础,让我们看一下第一个数字。在上面的示例中,五个数字以0开头,五个以1开头,九个以2开头。当第一个数字为2时,最大数字保证为2.因此,我们可以将2与9个2位数字组合基地3。
当第一个数字小于组中的最大数字时,我们可以将它与基数3的9个2位数字组合,但我们不能使用与4 2不明确的4个2位数字。 -digit number of base 2.这给了我们5个数字0和1的可能性。这些可能性 - 02,12,20,21和22 - 可以描述为具有两个数字的唯一数字,根据相同的方案,但是抵消:
4 0 2
5 1 2
6 2 0
7 2 1
8 2 2
这导致递归解决方案:
这是Python中的一个例子。该表示作为数字列表返回,因此您可以将[^,3290,990]表示为2 ^ 32 - 。
import math
def repres(x, ndigit, base):
"""Straightforward representation of x in given base"""
s = []
while ndigit:
s += [x % base]
x /= base
ndigit -= 1
return s
def encode(x, ndigit):
"""Encode according to min-base, fixed-digit order"""
if ndigit <= 1:
return [x]
base = int(x ** (1.0 / ndigit)) + 1
if base <= 2:
return repres(x, ndigit, 2)
x0 = (base - 1) ** ndigit
nprev = (base - 1) ** (ndigit - 1)
ncurr = base ** (ndigit - 1)
ndiff = ncurr - nprev
area = (x - x0) / ndiff
if area < base - 1:
xx = x0 / (base - 1) + x - x0 - area * ndiff
return [area] + encode(xx, ndigit - 1)
xx0 = x0 + (base - 1) * ndiff
return [base - 1] + repres(x - xx0, ndigit - 1, base)
for x in range(32):
r = encode(x, 3)
print x, r