Кроссплатформенный воспроизводимый генератор чисел
Мне нужен генератор "случайных" чисел, который выдает тот же результат для заданного начального числа в Windows, Mac, Linux, iOS и Android. Сейчас попробовал std::rand
а также boost::random_int_generator
с boost::mt19937
но, к сожалению, результат отличается для Windows и Mac.
Кто-нибудь знает о реализации (C++), которая надежно работает на всех платформах?
РЕДАКТИРОВАТЬ 1:
Чтобы быть более конкретным, разница между числами из boost::mt19937
в Windows и Mac показано, что в Windows (2) генерируются дополнительные блоки чисел. Это выглядит действительно странно, потому что большинство чисел совпадают с этими блоками, присутствующими только в Windows.
РЕДАКТИРОВАТЬ 2:
boost::mt19937
надежно работает на всех платформах. Наши проблемы не были ошибкой там.
3 ответа
Различные числа привели к куску glm
код, который мы использовали. Они используют неопределенный порядок оценки аргументов, что хорошо для почти случайных целей, но не для случаев, когда вам нужны детерминированные числа (очевидно). Поэтому мы исправили код для наших целей и успешно используем boost::mt19937
на Windows, Mac, Linux, Android и iOS.
Извините за путаницу.
Если вам не нужен слишком высококачественный ГСЧ, вы можете реализовать его самостоятельно в виде однострочника, как описано здесь: https://en.wikipedia.org/wiki/Linear_congruential_generator Линейные конгруэнтные гены недавно получили довольно дурную славу., но для многих практических целей они хороши.
Пока вы осторожны с использованием только типов гарантированного размера (uint32_t и т. Д.), Все будет в порядке на всех платформах.
Если вам нужен более качественный ГСЧ, вы снова можете внедрить Mersenne Twister ( https://en.wikipedia.org/wiki/Mersenne_Twister) самостоятельно, но это будет сложнее.
Еще один способ - использовать AES (или любой другой блочный шифр в этом отношении, например, Chacha20) в режиме CTR (используя некоторый предопределенный ключ) в качестве PRNG; это будет самое известное (криптографическое) качество:-). Это не займет много кода на вашей стороне, но вам нужно будет связать реализацию AES (они широко доступны).
РЕДАКТИРОВАТЬ: пример псевдокода для иллюстрации PRNG на основе криптографии:
class CryptoBasedPRNG {
uint128_t key;
uint128_t count;
CryptoBasedPRNG(whatever-type seed) {
//derive key and initial counter from seed
// we'll be using SHA256, but any other split should do (like odd bits/even bits of seed)
uint256_t sha = sha256(seed);
key = low_128bits(sha);
count = high_128bits(sha);
}
uint128_t random_128_bits() {
count += 1;//with wraparound
return aes128(key,count);//encrypting 'count' as input data for aes128 (in ECB mode, if anybody asks about mode at this point)
}
}
Скорее просто и очень случайно.
Вы можете попробовать PCG-Random с http://www.pcg-random.org/
порядочный, быстрый, портативный