Существует другой способ делать «случайные» упорядоченные числа с LFSR, взгляните на:
http://en.wikipedia.org/wiki/Linear_feedback_shift_register
с помощью этой методики вы можете получить упорядоченное случайное число по индексу и убедиться, что значения не дублируются.
Но это не истинные случайные числа, потому что случайная генерация детерминирована [/. g4]
Но в зависимости от вашего случая вы можете использовать эту технику, уменьшая количество обработки при генерации случайных чисел при использовании тасования.
Здесь алгоритм LFSR в java (я взял его где-то, я не remeber):
public final class LFSR {
private static final int M = 15;
// hard-coded for 15-bits
private static final int[] TAPS = {14, 15};
private final boolean[] bits = new boolean[M + 1];
public LFSR() {
this((int)System.currentTimeMillis());
}
public LFSR(int seed) {
for(int i = 0; i < M; i++) {
bits[i] = (((1 << i) & seed) >>> i) == 1;
}
}
/* generate a random int uniformly on the interval [-2^31 + 1, 2^31 - 1] */
public short nextShort() {
//printBits();
// calculate the integer value from the registers
short next = 0;
for(int i = 0; i < M; i++) {
next |= (bits[i] ? 1 : 0) << i;
}
// allow for zero without allowing for -2^31
if (next < 0) next++;
// calculate the last register from all the preceding
bits[M] = false;
for(int i = 0; i < TAPS.length; i++) {
bits[M] ^= bits[M - TAPS[i]];
}
// shift all the registers
for(int i = 0; i < M; i++) {
bits[i] = bits[i + 1];
}
return next;
}
/** returns random double uniformly over [0, 1) */
public double nextDouble() {
return ((nextShort() / (Integer.MAX_VALUE + 1.0)) + 1.0) / 2.0;
}
/** returns random boolean */
public boolean nextBoolean() {
return nextShort() >= 0;
}
public void printBits() {
System.out.print(bits[M] ? 1 : 0);
System.out.print(" -> ");
for(int i = M - 1; i >= 0; i--) {
System.out.print(bits[i] ? 1 : 0);
}
System.out.println();
}
public static void main(String[] args) {
LFSR rng = new LFSR();
Vector vec = new Vector();
for(int i = 0; i <= 32766; i++) {
short next = rng.nextShort();
// just testing/asserting to make
// sure the number doesn't repeat on a given list
if (vec.contains(next))
throw new RuntimeException("Index repeat: " + i);
vec.add(next);
System.out.println(next);
}
}
}
Вот пример:
extern const int b;
template<int, int>
void f(int);
template<int, const int &>
void f(long);
template<class>
void g() {
f<0, b>(0);
}
// #1
extern const int b = 0;
int main(){
g<int>();
}
// #2
Гипотетическое создание экземпляра в # 1 вызовет void f<0, b>(long)
, поскольку b
не является постоянным выражением в этой точке, поэтому (int)
перегружает SFINAE далеко. Создание экземпляра в # 2 (которое является точкой инстанцирования g<int>
) вызовет void f<0, 0>(int)
, потому что к тому времени b
является постоянным выражением, перегрузка (int)
жизнеспособна и выигрывает разрешение перегрузки.