【问题标题】:Digit manipulation number conversion数字操作数字转换
【发布时间】:2015-08-04 01:29:49
【问题描述】:

我有从 0000 到 1440 的 4 位数字。我想生成一个等效的四位数字。这意味着我可以将数字与等效数字相反。基本要求是等效号码必须与原号码完全不同。有没有一个很好的等式来做到这一点? 例如,每个数字都可以替换为10 - digit。因此,1440 变为 9660,1254 变为 9756。

谢谢。

【问题讨论】:

  • 请编辑您的问题以包含某些指定输入的示例输出。还请显示您迄今为止尝试过的Minimal, Complete, and Verifiable Example,包括说明它如何不满足您的要求,例如显示实际和预期的输出、构建错误、运行时错误等。
  • 每个数字 n -> (n+1)%10 怎么样?
  • 或者确实是x += 1111。扭转它:x -= 1111
  • 很难理解你的问题。然而,一个简单的编码是XOR cipher
  • 什么是“等价物”?

标签: c++ algorithm math encoding digit


【解决方案1】:

您可以使用周期为 10000 的 Linear Congruential 生成器。这是一个伪随机数生成器,它循环遍历 0-9999 范围内的每个数字一次且仅一次。要生成您的号码,只需获取原始号码并计算 LCG 序列中的下一个号码。

LCG 使用以下公式生成随机数:

Xn+1 = ((Xn * a) + c) mod m

要生成 4 位数字,m 应为 10000(范围为 0-9999)。

为了保证没有重复(“完整周期”),您必须使用以下标准选择 a 和 c 的值:

c 和 m 互质

a - 1 能被 m 的所有素因数整除

如果 m 是 4 的倍数,a - 1 是 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) 找回原来的号码。

【讨论】:

  • 如何选择数字M、a和c?我正在尝试扩展到 6 位,但无法使其工作(M = 1000000,a = 474581,c = 760021)。
  • c 应该是素数(只要 M 不是 c 的倍数,这将确保 M 和 c 互素)。 760021 不是素数,因为它是 107 * 7103。试试 760043。您可以使用这样的在线应用程序测试素数:primes.utm.edu/curios/includes/primetest.php
  • 你有 int 溢出吗?您可能需要使用 long。
【解决方案2】:

这或许更像是一条评论。

我认为您的问题相当模糊,因为您没有定义“完全不同”。典型的“简单”方法如下:

  • 颠倒数字。
  • 用这些数字替换其他数字(一种简单的方法是将每个数字加 1)。
  • 用数字对替换其他数字对。

而且,你当然可以将这些结合起来。

在您的情况下,您从 1,441 的范围开始并映射到更大的范围 (10,000)。这实际上为您提供了更大范围的可能映射。

然而,关键是“不同有多大不同”?你应该修改你的问题来解释这一点。

【讨论】:

  • 例如,我有一个数字 1334。假设等值是 2445。我还有另一个数字 1335,我们希望它的等值数字是 4547,或者不是纯粹加减数字。
  • 反向和替换通常足以用于视觉混淆。对于真正的加密来说不够好,但对于某些应用程序来说已经足够了。
猜你喜欢
  • 2015-05-07
  • 2016-01-10
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多