数字操作数字转换
Digit manipulation number conversion
我有从 0000 到 1440 的 4 位数字。我想生成一个等效的四位数字。这意味着我可以将数字与等效数字相反。基本要求是等效数字必须与原始数字完全不同。有没有一个好的方程式可以做到这一点?
例如,每个数字都可以用 10 - digit
代替。这样,1440就变成了9660,1254就变成了9756。
谢谢。
这也许更像是一条评论。
我觉得你的问题比较含糊,因为你没有定义"completely different"。典型的 "easy" 方式类似于:
- 反转数字。
- 用这些数字替换其他数字(一种简单的方法是将每个数字递增 1)。
- 用数字对替换其他数字对。
而且,您当然可以将这些结合起来。
在您的例子中,您从 1,441 的范围开始并映射到更大的范围 (10,000)。这实际上为您提供了更大范围的可能映射。
不过,重点是"how different is different"?你应该修改你的问题来解释这一点。
您可以使用周期为 10000 的 Linear Congruential 生成器。这是一个伪随机数生成器,它循环遍历 0-9999 范围内的每个数字一次且仅一次。要生成您的号码,只需取原始号码并计算 LCG 序列中的下一个号码。
LCG 使用以下公式生成随机数:
Xn+1 = ((Xn * a) + c) mod m
要生成 4 位数字,m 应为 10000(范围为 0-9999)。
为了保证不重复(“完整周期”),您必须使用以下标准 select a 和 c 的值:
c and m are relatively prime
a - 1 is divisible by all prime factors of m
a - 1 is a multiple of 4 if m is a multiple of 4.
10000的质因数是2和5,而且还能被4整除,所以20+1的任意倍数都可以作为a的合适值。对于 c 只需选择一个相当大的素数。
例如:m = 10000,a = 4781,c = 7621
要反其道而行之,您需要使函数可逆。请参阅 this answer 了解其背后的数学解释。
这是一个简单的实现:
#define M (10000)
#define A (4781)
#define C (7621)
int extendedEuclidY(int a, int b);
int extendedEuclidX(int a, int b)
{
return (b==0) ? 1 : extendedEuclidY(b, a-b*(a/b));
}
int extendedEuclidY(int a, int b)
{
return (b==0) ? 0 : extendedEuclidX(b, a-b*(a/b)) - (a/b) * extendedEuclidY(b, a-b*(a/b));
}
int forward(int x)
{
return ((x*A)+C)%M;
}
int backward(int x)
{
return ((extendedEuclidX(A, M)*(x-C)%M)+M)%M;
}
int main()
{
int x;
for(x=0; x<1440; x++)
{
printf("%d <-> %d\n", backward(forward(x)), forward(x));
}
return 0;
}
我已经从链接的答案中改编了 extendedEuclid
函数。
forward(x)
找到你的对等号码,backward(x)
找回原来的号码。
我有从 0000 到 1440 的 4 位数字。我想生成一个等效的四位数字。这意味着我可以将数字与等效数字相反。基本要求是等效数字必须与原始数字完全不同。有没有一个好的方程式可以做到这一点?
例如,每个数字都可以用 10 - digit
代替。这样,1440就变成了9660,1254就变成了9756。
谢谢。
这也许更像是一条评论。
我觉得你的问题比较含糊,因为你没有定义"completely different"。典型的 "easy" 方式类似于:
- 反转数字。
- 用这些数字替换其他数字(一种简单的方法是将每个数字递增 1)。
- 用数字对替换其他数字对。
而且,您当然可以将这些结合起来。
在您的例子中,您从 1,441 的范围开始并映射到更大的范围 (10,000)。这实际上为您提供了更大范围的可能映射。
不过,重点是"how different is different"?你应该修改你的问题来解释这一点。
您可以使用周期为 10000 的 Linear Congruential 生成器。这是一个伪随机数生成器,它循环遍历 0-9999 范围内的每个数字一次且仅一次。要生成您的号码,只需取原始号码并计算 LCG 序列中的下一个号码。
LCG 使用以下公式生成随机数:
Xn+1 = ((Xn * a) + c) mod m
要生成 4 位数字,m 应为 10000(范围为 0-9999)。
为了保证不重复(“完整周期”),您必须使用以下标准 select a 和 c 的值:
c and m are relatively prime
a - 1 is divisible by all prime factors of m
a - 1 is a multiple of 4 if m is a multiple of 4.
10000的质因数是2和5,而且还能被4整除,所以20+1的任意倍数都可以作为a的合适值。对于 c 只需选择一个相当大的素数。
例如:m = 10000,a = 4781,c = 7621
要反其道而行之,您需要使函数可逆。请参阅 this answer 了解其背后的数学解释。
这是一个简单的实现:
#define M (10000)
#define A (4781)
#define C (7621)
int extendedEuclidY(int a, int b);
int extendedEuclidX(int a, int b)
{
return (b==0) ? 1 : extendedEuclidY(b, a-b*(a/b));
}
int extendedEuclidY(int a, int b)
{
return (b==0) ? 0 : extendedEuclidX(b, a-b*(a/b)) - (a/b) * extendedEuclidY(b, a-b*(a/b));
}
int forward(int x)
{
return ((x*A)+C)%M;
}
int backward(int x)
{
return ((extendedEuclidX(A, M)*(x-C)%M)+M)%M;
}
int main()
{
int x;
for(x=0; x<1440; x++)
{
printf("%d <-> %d\n", backward(forward(x)), forward(x));
}
return 0;
}
我已经从链接的答案中改编了 extendedEuclid
函数。
forward(x)
找到你的对等号码,backward(x)
找回原来的号码。