【问题标题】:This code works online, but not from my own compiler此代码在线工作,但不是来自我自己的编译器
【发布时间】:2015-01-31 03:54:50
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
main() {
    int j, u[23] = {0};
    while (!u[19]) {
        while (u[j = rand() % 23]++)
            ;
        putchar("uatChks rteJ r hon,\neca"[j]);
    }
}

是一段用于打印的混淆代码

只是另一个 C 黑客,

它适用于我尝试过的两种不同的在线编译器/解释器(ideone.com 和 codepad.org),但当我使用 GCC 运行它时却不行。

当我使用 GCC 构建并运行它时,它会打印:

,cthehasok tre anu

在我的计算机上,我正在使用以下命令构建它:

gcc C:\Programming\c\JACH.c -o JACH

我认为问题与rand() 函数有关,也可能与RAND_MAX 宏有关:

在我的编译器中,RAND_MAX 被定义为 32767,而在 ideone.com 上,它是 2147483647。我不确定这是否真的与它有关,但我确信rand() 是问题所在,在运行了这样的测试之后:

srand(0);
int i;
for (i=1;i<4;i++) {
    printf("%d: %d\n", i, rand() % 23);
}

这段代码在不同的编译器中产生了非常不同的结果,

gcc:

1: 15
2: 14
3: 9

ideone.com:

1: 11
2: 0
3: 6

有谁知道如何强制我的编译器提供与 ideone.com/online 编译器相同的结果?

【问题讨论】:

  • 我不确定您是否可以依赖 rand() 作为跨系统的相同实现。
  • @JS1 好的,有什么方法可以测试吗?
  • @JS1 是的,我明白你的意思,但我该如何测试/修复它?
  • 您可以使用一个简单的程序对其进行测试,该程序会打印前几个rand() 结果。我知道如果你不播种,你总是会在一台机器上从rand() 获得相同的序列(这对测试很有用),但请记住 - 它是一个随机数生成器。请参阅上一个问题stackoverflow.com/questions/1026327/…

标签: c build compilation sublimetext2


【解决方案1】:

linear congruential generator 是一种生成伪随机数的简单方法,只需很少的代码即可实现。

实际上,如果您使用生成最大长度序列的序列,则无需检查已返回的值,因为它会在重复之前生成每个值一次。

此代码适用于任何系统,并且由于它不依赖于除putchar() 之外的任何库调用,因此它始终会产生相同的输出。 while() 循环将在 j 返回其原始值零时退出:

#include <stdio.h>
int main() {
  int j=0;
  while (putchar("\nae ,hhtr tseCouk nJcra"[j=(j*93+19)%23]) && j);
  return 0;
}

更新

您提供的数字序列(1804289383、846930886、1681692777、1714636915)表明 ideone 使用 GLIBC random number generator,它从基于种子值初始化的 34 个整数池中计算随机数。

如果您使用默认种子值 1(不是零,实际上是不允许的,内部更改为 1),则可以完全省略初始化阶段,最终得到这个函数:

int default_rand() {
  static unsigned int i=3, r[34] = { 0xf3bec5da, 0x991539b1, 0x16a5bce3, 0x6774a4cd,
             0x55928aca, 0xc34a51a2, 0x73b5def3, 0x3e01511e, 0x4e508aaa, 0x61048c05,
             0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
             0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
             0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
             0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41 };
  i = (i+1) % 34;
  return (r[i] = r[(i+3)%34] + r[(i+31)%34]) >> 1;
}

您可以自己验证,在调用srand(0)srand(1) (ideone link) 之后,此函数生成的数字与连续调用rand() 完全相同。

【讨论】:

  • 你能否创建一个线性同余生成器,按顺序生成这些数字:1804289383、846930886、1681692777、1714636915,当种子为 0 时,就像 rand() 在 ideone.com 上所做的那样?
  • @theonlygusti 这些数字不是由线性同余生成器生成的。 Use the code on this page instead.
  • 您能否将该链接添加到您的答案中并提供一个示例,也许可以作为可以与 rand() 一样使用的函数?
  • 哇,谢谢!我也不知道srand 的要求,但这很有效,正是我需要的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2022-08-08
  • 1970-01-01
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多