简单的伪随机算法

发布于 2024-08-07 07:12:20 字数 852 浏览 12 评论 0原文

我需要一个伪随机生成器,它将一个数字作为输入并返回另一个数字,该数字是可再现的并且似乎是随机的。

  • 每个输入数字应与一个输出数字完全匹配,反之亦然
  • 相同的输入数字始终会产生相同的输出数字
  • 相邻的连续输入数字(例如 1 和 2)应产生完全不同的输出数字(例如 1 => 9783526 , 2 => 283)

它一定不是完美的,它只是为了创建随机但可重复的测试数据。

我使用 C#。


我不久前写了一段有趣的代码,它产生了一些随机的东西。

  public static long Scramble(long number, long max) 
  {
    // some random values 
    long[] scramblers = { 3, 5, 7, 31, 343, 2348, 89897 };
    number += (max / 7) + 6;
    number %= max;
    // shuffle according to divisibility
    foreach (long scrambler in scramblers) 
    {
      if (scrambler >= max / 3) break;
      number = ((number * scrambler) % max) 
        + ((number * scrambler) / max);
    }

    return number % max;
  }

我想要更好、更可靠的东西,可以处理任何大小的数字(没有最大参数)。

使用 CRC 算法可以解决这个问题吗?或者一些乱七八糟的东西。

I'm need a pseudo-random generator which takes a number as input and returns another number witch is reproducible and seems to be random.

  • Each input number should match to exactly one output number and vice versa
  • same input numbers always result in same output numbers
  • sequential input numbers that are close together (eg. 1 and 2) should produce completely different output numbers (eg. 1 => 9783526, 2 => 283)

It must not be perfect, it's just to create random but reproducible test data.

I use C#.


I wrote this funny piece of code some time ago which produced something random.

  public static long Scramble(long number, long max) 
  {
    // some random values 
    long[] scramblers = { 3, 5, 7, 31, 343, 2348, 89897 };
    number += (max / 7) + 6;
    number %= max;
    // shuffle according to divisibility
    foreach (long scrambler in scramblers) 
    {
      if (scrambler >= max / 3) break;
      number = ((number * scrambler) % max) 
        + ((number * scrambler) / max);
    }

    return number % max;
  }

I would like to have something better, more reliable, working with any size of number (no max argument).

Could this probably be solved using a CRC algorithm? Or some bit shuffling stuff.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

謌踐踏愛綪 2024-08-14 07:12:20

我从这个答案中删除了微软代码,GNU代码文件更长,但基本上它包含来自 http://cs.uccs.edu/~cs591/bufferOverflow/glibc-2.2.4/stdlib/random_r.c

int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;

为了您的目的,种子是state[0] 所以它看起来更像

int getRand(int val)
{
    return ((val * 1103515245) + 12345) & 0x7fffffff;
}

I remove the microsoft code from this answer, the GNU code file is a lot longer but basically it contains this from http://cs.uccs.edu/~cs591/bufferOverflow/glibc-2.2.4/stdlib/random_r.c :

int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;

for your purpose, the seed is state[0] so it would look more like

int getRand(int val)
{
    return ((val * 1103515245) + 12345) & 0x7fffffff;
}
吹梦到西洲 2024-08-14 07:12:20

您(也许)可以使用 Random 类在 C# 中轻松完成此操作:

public int GetPseudoRandomNumber(int input)
{
    Random random = new Random(input);
    return random.Next();
}

由于您使用输入显式播种 Random,因此每次给定相同的输入值时,您都会获得相同的输出。

You (maybe) can do this easily in C# using the Random class:

public int GetPseudoRandomNumber(int input)
{
    Random random = new Random(input);
    return random.Next();
}

Since you're explicitly seeding Random with the input, you will get the same output every time given the same input value.

无语# 2024-08-14 07:12:20

tausworthe 生成器实现起来很简单并且速度相当快。以下伪代码实现具有完整的周期(2**31 - 1,因为零是固定点):

def tausworthe(seed)
  seed ^= seed >> 13
  seed ^= seed << 18
  return seed & 0x7fffffff

我不懂 C#,但我假设它有 XOR (^) 和位与 C 中一样的 shift (<<, >>) 运算符。

设置初始种子值,并使用 seed = tausworthe(seed)< 进行调用/代码>。

A tausworthe generator is simple to implement and pretty fast. The following pseudocode implementation has full cycle (2**31 - 1, because zero is a fixed point):

def tausworthe(seed)
  seed ^= seed >> 13
  seed ^= seed << 18
  return seed & 0x7fffffff

I don't know C#, but I'm assuming it has XOR (^) and bit shift (<<, >>) operators as in C.

Set an initial seed value, and invoke with seed = tausworthe(seed).

浪推晚风 2024-08-14 07:12:20

前两个规则建议输入的固定或输入种子排列,但第三个规则需要进一步的变换。

对于指导该转换的输出应该是什么有任何进一步的限制吗? - 例如,是否有一组输入输出值可供选择?

如果唯一的指导是“无最大值”,我将使用以下内容...

  1. 对整个输入应用哈希算法以获取第一个输出项。 CRC 可能有效,但要获得更多“随机”结果,请使用加密哈希算法,例如 MD5。

  2. 对输入使用下一个排列算法(Google 上有大量链接)。

  3. 重复 hash-then-next-permutation,直到找到所有需要的输出。

不过,下一个排列可能有点过头了,您可能可以在重做哈希之前增加第一个输入(并且可能在溢出时增加第二个输入,依此类推)。

对于加密式散列,您需要一个密钥 - 只需在开始之前从输入中派生一些内容即可。

The first two rules suggest a fixed or input-seeded permutation of the input, but the third rule requires a further transform.

Is there any further restriction on what the outputs should be, to guide that transform? - e.g. is there an input set of output values to choose from?

If the only guide is "no max", I'd use the following...

  1. Apply a hash algorithm to the whole input to get the first output item. A CRC might work, but for more "random" results, use a crypto hash algorithm such as MD5.

  2. Use a next permutation algorithm (plenty of links on Google) on the input.

  3. Repeat the hash-then-next-permutation until all required outputs are found.

The next permutation may be overkill though, you could probably just increment the first input (and maybe, on overflow, increment the second and so on) before redoing the hash.

For crypto-style hashing, you'll need a key - just derive something from the input before you start.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文