Детерминированная случайность в Objective C

Этот код в Java является реализацией случайного шага Кнута, но является детерминированным, управляемым начальным числом генератора случайных чисел.

public String shuffleString(String data, long shuffleSeed) {
    if(shuffleSeed!=0) {
        Random rnd = new Random(shuffleSeed);
        StringBuilder sb = new StringBuilder(data);
        int n = data.length();
        while(n>1) {
            int k = rnd.nextInt(n--);
            char t = sb.charAt(n);
            sb.setCharAt(n, sb.charAt(k));
            sb.setCharAt(k, t);
        }
        return sb.toString();
    }
    else {
        return data;
    }
}

Как я могу реализовать детерминированный тасование в Задаче C, которое выводит тот же порядок тасования при том же начальном числе? Я использую srandom(_shuffleSeed); и random()%(n--), зная, что arc4_random лучше, но его нельзя засеять.

- (NSString*) shuffleString:(NSString*) data withShuffleSeed:(int) shuffleSeed {
    if(shuffleSeed!=0) {
        srandom(_shuffleSeed);
        NSMutableString *result = [[NSMutableString alloc] initWithString:data];
        unsigned long n = data.length;
        while(n>1) {
            unsigned long k = random()%(n--);
            unichar t = [result characterAtIndex:n];
            NSRange r1 = {n,1};
            [result replaceCharactersInRange:r1 withString:[NSString stringWithFormat:@"%c", [result characterAtIndex:k]]];
            NSRange r2 = {k,1};
            [result replaceCharactersInRange:r2 withString:[NSString stringWithFormat:@"%c", t]];
        }
        return result;
    }
    else {
        return data;
    }
}

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

1 ответ

Решение

Существует много алгоритмов генерации псевдослучайных чисел, которые используют начальное число. Вы не можете предполагать, что в стандартной библиотеке Java используется точно такой же алгоритм, как srandom/random в цель С.

Генератор случайных чисел Java использует:

В классе используется 48-разрядное начальное число, которое модифицируется с использованием линейной конгруэнтной формулы. (См. Дональд Кнут, "Искусство компьютерного программирования", том 3, раздел 3.2.1.)

Это больше не дает никаких гарантий, хотя никогда не изменяется по причинам обратной совместимости.

Ваши варианты:

  • Возьмите исходный код Java и преобразуйте его в Objective-C (или надейтесь, что кто-то еще делал это раньше). Обратите внимание, что исходный код Java лицензируется по лицензии GPL или ограниченной лицензии Oracle. Если вы берете версию под лицензией GPL, это влияет на лицензию, которую вы можете использовать для собственного кода.
  • Найдите источник генератора случайных чисел в Objective-C и преобразуйте его в Java. (Который также может иметь лицензионные ограничения, а источник может быть недоступен). Или, может быть, алгоритм задан более правильно, чтобы вы могли реализовать его на Java исключительно из документации.
  • Найдите другой генератор случайных чисел с реализацией Java и Object-C, которые дают идентичные результаты (или пишите один)
Другие вопросы по тегам