【问题标题】:How to generate a series of random numbers with the C/C++ preprocessor如何使用 C/C++ 预处理器生成一系列随机数
【发布时间】:2011-09-23 19:16:11
【问题描述】:

我想用 C 预处理器生成一系列随机数,并将它们存储在变量中以供我的程序使用。

目标:

我想在每次构建程序时生成一组“唯一”的随机数。存储随机数的一小部分变量将被有意义的(即非随机)数字覆盖。我希望黑客不可能通过调试程序或比较多个版本来区分有意义的数字和随机数。我希望构建过程是自动化的和独立的。我希望实现可以跨 Visual Studio 和 GCC 移植。

澄清:

  1. 必须在编译时进行计算,而不是在程序执行时进行。调试程序的任何人都应该只能看到,例如,一个变量被初始化为一个常量(随机数)。
  2. 随机数应该是整数。
  3. 随机数生成器应以某种方式从__DATE____TIME__ 播种,以便不同的构建会产生不同的随机数。
  4. 最好能够指定随机数的范围(例如,从 1 到 100),但并非绝对必要。
  5. 最好能够指定要生成的随机数的总数(例如,声明 1000 个变量并将每个变量初始化为一个随机数),但并非绝对必要。

目前的尝试:

  1. 预处理器中的上一个算术线程:Can the C preprocessor perform integer arithmetic? 要点是 #if 条件可以评估算术。
  2. 谷歌搜索显示,除了算术,移位和位操作也可以通过#if 进行评估。我已经用 Visual Studio C++ 确认了这一点。
  3. 简单随机数生成器的候选人:http://www.ciphersbyritter.com/NEWS4/RANDC.HTM#369B5E30.65A55FD1@stat.fsu.edu 这些生成器中的任何一个,或者任何不可能从给定的一系列随机数进行逆向工程的生成器都可以,因为我不需要性能特别好的生成器。为了这个练习,我们可以使用以下示例:

    unsigned long jcong=380116160;
    #define CONG (jcong=69069*jcong+1234567)
    
  4. 我认为基本问题是在对生成器的连续调用之间存在存储在变量 jcong 中的状态。据我所知,预处理器不支持变量赋值。也许有一些聪明的递归宏可以解决问题?

  5. 我能得到的最接近但不满足由预处理器执行的目标是:

    unsigned long jcong=380116160;
    unsigned long randomBlock[] = {jcong=69069*jcong+1234567, jcong=69069*jcong+1234567};
    

    我已经在 Visual Studio C++ 中确认这确实将数组成员初始化为不同的随机数。但是,调试器仍会逐步完成初始化。

这是一个纯粹的编程/实现问题,所以请不要宣传预处理器的邪恶或打击黑客的徒劳。

【问题讨论】:

  • 你真的需要预处理器还是C++模板就可以了?
  • 预处理器不是必需的。我只需要通过可执行文件将其全部“破解”即可。
  • @Dale “我只需要这一切都是“不可破解的””——我有坏消息要告诉你,那是行不通的。没有一个系统是牢不可破的。
  • 我可以推荐VS的msbuild.exe吗?因为它的构建过程是不可预测的。我可以在一次运行中构建而不会出现任何错误,而在下一次构建时不触及任何东西,它会产生错误。

标签: c visual-c++ random c-preprocessor


【解决方案1】:

您必须用实际生成可接受的半随机值的东西替换随机生成器序列,但这部分应该很容易。

您必须在编译时使用-DSEED=... 定义一个随机种子。 不知道如何使用 __TIME____DATE__ 来做到这一点,因为它们是字符串。

#include <stdio.h>

template <int N>
struct Random {
    enum { value = 7 * Random<N-1>::value + 17 };
};

template <>
struct Random<1> {
    enum { value = SEED};
};

template <int N, int BEG, int END>
struct RandomIn {
    enum { value = BEG + Random<N>::value % (END-BEG) };
};

int main() {
    printf("%d %d", RandomIn<2, 5, 10>::value, RandomIn<3, 5, 10>::value);
    return 0;
}

【讨论】:

  • 请问有没有办法灵活配置变量个数?就像现在一样,我必须为每个变量硬编码一个 RandomIn
  • 我不明白你的问题。它为每个 N 创建一个不同的随机变量。如果你需要 100 个,请使用 100 个不同的 N-s。
  • 是的,如果我想要 100 个变量,我可以使用 100 个不同的 N。如果我想要 1000 个变量,我将不得不硬编码 1000 个不同的 N。我想知道是否有一些简单的机制,例如 int x[100] 与 int x[1000],其中单个编译时参数将控制生成多少变量和随机数。非常感谢您到目前为止的回答;我只是希望可以在其上添加一些东西以获得额外的可配置性。
  • 在某些时候你必须在你的代码中使用这些变量,然后你必须明确地写出那些 N 数字......那有什么意义呢?您需要任何随机变量数组吗?这就是你想要的吗?
【解决方案2】:

所以,这里是接近需求的解决方案:

// pprand.h

#include <boost/preprocessor/slot.hpp>

#ifndef PP_RAND_SEED
#define PP_RAND_SEED    (((PP_RAND_MIN + PP_RAND_MAX) * 0x1f7) ^ 0x1e3f75a9)
#endif

#define BOOST_PP_VALUE ((PP_RAND_SEED * 214013 + 2531011) % 65536)
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#undef PP_RAND_SEED
#define PP_RAND_SEED    BOOST_PP_SLOT(1)

#define BOOST_PP_VALUE (PP_RAND_MIN + PP_RAND_SEED % (PP_RAND_MAX - PP_RAND_MIN))
#include BOOST_PP_ASSIGN_SLOT(2)
#undef BOOST_PP_VALUE

#ifdef PP_RAND
#undef PP_RAND
#endif

#define PP_RAND BOOST_PP_SLOT(2)

你可以这样使用它:

// Pseudo random number range.
#define PP_RAND_MIN 0
#define PP_RAND_MAX 100

// Pseudo random number seed.
#define PP_RAND_SEED 123
#include "pprand.h"

// Got it!
#pragma message("PP_RAND value:" _CRT_STRINGIZE(PP_RAND))

要了解有关此方法的更多信息,请访问我的博客:http://alexander-stoyan.blogspot.com/2012/07/getting-pseudo-random-numbers-at.html

【讨论】:

  • 感谢您发布您的答案!请务必仔细阅读FAQ on Self-Promotion。另请注意,每次链接到您自己的网站/产品时,都要求发布免责声明。我正在为您编辑所需的免责声明。
猜你喜欢
  • 2011-07-18
  • 1970-01-01
  • 2020-10-09
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多