Как сгенерировать серию случайных чисел с помощью препроцессора C / C ++ - PullRequest
3 голосов
/ 27 июня 2011

Я хотел бы сгенерировать серию случайных чисел с препроцессором C и сохранить их в переменных для использования моей программой.

ЦЕЛИ:

Iхотел бы генерировать «уникальный» набор случайных чисел каждый раз, когда я строю свою программу.Небольшое подмножество переменных, хранящих случайные числа, будет перезаписано значимыми (то есть неслучайными) числами.Я бы хотел, чтобы хакер, отладив программу или сравнив несколько сборок, не смог отличить значащие числа от случайных чисел.Я хотел бы, чтобы процесс сборки был автоматизирован и самодостаточен.Я хотел бы, чтобы реализация была переносимой между Visual Studio и GCC.

ПОЯСНЕНИЯ:

  1. Вычисления должны выполняться во время компиляции, а не при выполнении программы.Любой, кто отлаживает программу, должен видеть только, например, переменную, инициализируемую константой (случайное число).
  2. Случайные числа должны быть целыми числами.
  3. Генератор случайных чиселследует каким-то образом отсеять из __DATE__ и __TIME__, чтобы разные сборки давали разные случайные числа.
  4. Было бы предпочтительно, но не обязательно, иметь возможность указывать диапазондля случайных чисел (например, от 1 до 100).
  5. Было бы предпочтительно, но не обязательно, иметь возможность указывать общее количество генерируемых случайных чисел (например, объявлять 1000 переменных и инициализировать каждое вслучайное число).

ПОПЫТКИ SO FAR:

  1. Предыдущий поток по арифметике в препроцессоре: Может ли препроцессор C выполнять целочисленную арифметику? Суть в том, что условие #if может вычислять арифметику.
  2. Поиск в Google показывает, что помимо арифметики, операций сдвига и битовтакже может быть оценено #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 ++, что это действительно инициализирует элементы массива различными случайными числами.Однако отладчик все еще выполняет инициализацию.

Это чистый вопрос программирования / реализации, поэтому, пожалуйста, не обращайте внимания на зло препроцессора или тщетность борьбы с хакерами.

Ответы [ 2 ]

3 голосов
/ 14 июля 2012

Итак, вот решение, которое близко к требованиям:

// 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 / получать-псевдо-случайных чисел-at.html

1 голос
/ 28 июня 2011

Вы должны заменить последовательность генератора случайных чисел чем-то, что фактически генерирует приемлемые полуслучайные значения, но эта часть должна быть легкой.

Вы должны определить случайное начальное число с -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;
}
...