简体   繁体   English

如何使用C / C ++预处理器生成一系列随机数

[英]How to generate a series of random numbers with the C/C++ preprocessor

I would like to generate a series of random numbers with the C preprocessor, and store them in variables for use by my program. 我想用C预处理器生成一系列随机数,并将它们存储在变量中供我的程序使用。

OBJECTIVES: 目的:

I would like to generate a "unique" set of random numbers every time I build my program. 我想在每次构建程序时生成一组“唯一”的随机数。 A small subset of the variables storing the random numbers will be overwritten with meaningful (ie non-random) numbers. 存储随机数的变量的一小部分将被有意义的(即非随机的)数字覆盖。 I would like it to be impossible for a hacker, by debugging the program or comparing multiple builds, to be able to differentiate the meaningful numbers from the random numbers. 我希望黑客不可能通过调试程序或比较多个构建来区分有意义的数字和随机数。 I would like the build process to be automated and self-contained. 我希望构建过程自动化并且自包含。 I would like the implementation to be portable across Visual Studio and GCC. 我希望实现可以跨Visual Studio和GCC移植。

CLARIFICATIONS: 澄清:

  1. The calculations must be done at compile time, not at program execution. 计算必须在编译时完成,而不是在程序执行时完成。 Anyone debugging the program should only be able to see, for example, a variable being initialized to a constant (the random number). 调试程序的任何人都应该只能看到,例如,一个变量被初始化为一个常量(随机数)。
  2. The random numbers should be integers. 随机数应该是整数。
  3. The random number generator should be seeded, in some manner, from __DATE__ and __TIME__ , so that different builds will yield different random numbers. 随机数生成器应以某种方式从__DATE____TIME__ __DATE__ ,这样不同的构建将产生不同的随机数。
  4. It would be preferable, but not absolutely necessary, to be able to specify a range for the random numbers (eg from 1 to 100). 能够指定随机数的范围(例如从1到100)将是优选的,但不是绝对必要的。
  5. It would be preferable, but not absolutely necessary, to be able to specify the total number of random numbers to generate (eg declare 1000 variables and initialize each to a random number). 能够指定要生成的随机数的总数(例如,声明1000个变量并将每个变量初始化为随机数)将是优选的,但不是绝对必要的。

ATTEMPTS SO FAR: 到目前为止:

  1. Previous thread on arithmetic in the preprocessor: Can the C preprocessor perform integer arithmetic? 预处理器中关于算术的先前线程: C预处理器可以执行整数运算吗? The take-away is that the #if condition can evaluate arithmetic. 外卖是#if条件可以评估算术。
  2. Googling reveals that besides arithmetic, shift and bit operations can also be evaluated by the #if. 谷歌搜索显示除了算术,移位和位操作也可以由#if评估。 I have confirmed this with Visual Studio C++. 我已经使用Visual Studio C ++确认了这一点。
  3. Candidates for simple random number generators: http://www.ciphersbyritter.com/NEWS4/RANDC.HTM#369B5E30.65A55FD1@stat.fsu.edu Any one of these generators, or any generator that is impossible to reverse engineer from a given series of random numbers, would be fine because I don't need a particularly well behaved generator. 简单随机数发生器的候选者: http//www.ciphersbyritter.com/NEWS4/RANDC.HTM#369B5E30.65A55FD1@stat.fsu.edu这些发生器中的任何一个,或任何不能从给定的逆向工程中生成的发生器一系列随机数,没问题,因为我不需要特别好的发电机。 For the sake of this exercise, we can use the following as an example: 为了本练习,我们可以使用以下示例:

     unsigned long jcong=380116160; #define CONG (jcong=69069*jcong+1234567) 
  4. I think the basic problem is that there is state that is stored in the variable jcong between successive calls to the generator. 我认为基本问题是在连续调用生成器之间存在存储在变量jcong中的状态。 Variable assignment is not supported in the preprocessor, as far as I know. 据我所知,预处理器不支持变量赋值。 Perhaps there is some clever recursive macro that can do the trick? 也许有一些聪明的递归宏可以做到这一点?

  5. The closest I could get, but not satisfying my objective of being performed by the preprocessor, is: 我能得到的最接近但不满足预处理器执行的目标是:

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

    I have confirmed in Visual Studio C++ that this does indeed initialize the array members to different random numbers. 我已经在Visual Studio C ++中确认这确实将数组成员初始化为不同的随机数。 However, the debugger still steps through the initialization. 但是,调试器仍然会逐步完成初始化。

This is a pure programming/implementation question, so please, no proselytizing on the evils of the preprocessor or the futility of fighting hackers. 这是一个纯粹的编程/实现问题,所以请不要改变预处理器的邪恶或打击黑客的徒劳。

So, here is the solution that is close to requirements: 所以,这是接近要求的解决方案:

// 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)

You can use it like this: 你可以像这样使用它:

// 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))

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

You have to replace the Random generator sequence with something that actually generates acceptable semi-random values, but that part should be easy. 您必须将Random generator序列替换为实际生成可接受的半随机值的内容,但该部分应该很容易。

You have to define a random seed with -DSEED=... at compilation. 您必须在编译时使用-DSEED=...定义随机种子。 No idea how to do that with __TIME__ and __DATE__ because they are strings. 不知道如何使用__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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM