2013-09-18 4 views
2

Мне было интересно, как я могу генерировать уникальные случайные числа, кроме как из определенного. Например, если я хочу, чтобы генерировать числа в диапазоне 1 to 10 except from 3, вывод должен быть чем-то вроде этого:Создание уникальных случайных чисел, кроме определенного в C

7 6 1 2 4 9 5 8 10 
+0

Я думаю, что для случайного числа выход «мог», а не «должен». – Marc

+0

В стороне - уникальные и случайные несовместимы. Случайный выбор имеет ту же вероятность выбора 8 независимо от того, что номер 8 был только что выбран ранее. Большинство предоставленных ответов будут содержать дубликаты. Вам нужен алгоритм перетасовки колоды (как в колоде карт). @ Ответ Джони - единственная тасовка, которую я видел до сих пор. –

+0

Здесь нуждаются алгоритмы Фишера-Йейта или Флойда. – ChronoTrigger

ответ

2

Генерировать случайное число в диапазоне 1..9 и добавьте, если число больше или равно 3.

+2

Однако это не даст равномерного распределения. EDIT: Я идиот, игнорируйте это. –

+0

@JamesElderfield: Как так? Разве вы не были бы одинаково вероятны получить 10, так как вы бы получили 1? – Boris

+0

О, извините, вы правы. Я забираю это назад, мозг пропускает часть «или больше». –

2

Создать номер. Проверьте его значение, если число равно 3, генерирует другое. Если это не 3, используйте его.

EDIT: Мышление перед кофе - ужасный план. Если вы хотите получить каждое число в диапазоне в произвольном порядке, я согласен с тем, что другие говорят о перетасовках. Если, однако, вам нужно какое-то случайное подмножество диапазона, я бы сохранил список запрещенных значений. Перемешивание и получение только первых чисел n также подходят, если диапазон не очень большой (например, не что-то вроде 0 < x < INT_MAX).

Каждый раз, когда вы создаете число, проверяйте, если сгенерированное число находится в запрещенном списке, а если оно есть, сгенерируйте другое число. Каждый раз, когда вы создаете действительный номер, вы добавляете его в список, чтобы обеспечить, чтобы сгенерированные числа были уникальными. Список также должен быть инициализирован вашими нежелательными номерами (3 в приведенном примере).

4

Произвольное число 1 - 10 и удалить 3.

Это не имеет значения, если вы удалите 3 до или после перетасовки.

В качестве альтернативы, перемешайте число 1 - 9 и переименуйте 3 в 10 ...

Для перетасовки без смещения можно использовать, например, алгоритм Fisher-Yates. http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

0

Этот код будет генерировать уникальные случайные числа от минимального до максимального заданного диапазона.

#include<stdio.h> 
#include <stdbool.h> 
#include <stdlib.h> 
#include <time.h> 

int main() 
{ 

    int max_range, min_range, i = 0, rand_num; 

    srand((unsigned)time(NULL)); 
    printf("Enter your maximum of range: "); 
    scanf("%d", &max_range); 
    printf("Enter your minimum of range: "); 
    scanf("%d", &min_range); 
    bool digit_seen[max_range + 1]; // VLAs For C99 only 

    for (int i = min_range; i <= max_range; i++) 
     digit_seen[i] = false; 

    for (;;) 
    { 
     rand_num = rand() % max_range + min_range; 
     if(rand_num !=3) 
      if(!digit_seen[rand_num]) 
      { 
       printf("%d ", rand_num); 
       digit_seen[rand_num] = true; 
       i++; 
      } 
     if(i == (max_range - 1)) 
      exit(0); 
    }  
    return 0; 
} 
+0

Здесь вы генерируете слишком много случайных чисел. Представьте, что 8 из 9 чисел «видны» - вам, возможно, придется генерировать десятки чисел, просто чтобы (случайно!) Наткнуться на последний. Поскольку вы уже создаете список, сделайте это вместо этого: (1) выберите случайный номер из своего списка, (2) переместите последний элемент своего списка в эту позицию, (3) уменьшите длину списка. Повторяйте до тех пор, пока список не будет пуст. – usr2564301

+0

@ Jongware; Я не понимаю, как здесь будет работать ваша логика? o.O – haccks

+0

Ваш код будет слепо продолжать генерировать уже принятые случайные числа. Вам лучше заполнить список первым (в этом случае, исключая нежелательное значение), а затем выбрать случайный * из этого списка *. После использования * удалите * его из списка, чтобы он не был выбран снова. Остальное - бухгалтерия. – usr2564301

0

Вы можете попробовать так: -

unsigned int 
randomnumber(unsigned int min, unsigned int max) 
{ 
     double scaled = (double)rand()/RAND_MAX; 

     return (max - min +1)*scaled + min; 
} 

потом вы можете сделать это: -

x = randomnumber(1,10); 

if (x==3) 
{ x = x+1;} 

или

if (x!=3) 
{ printf("%d",x)} 
+0

Итак, результат «4» будет генерироваться 2x часто, чем все остальные цифры? – maxihatop

+0

@maxihatop: - Это всего лишь один подход. Может быть, OP может изменить его по своему усмотрению. !!! Надеюсь, это имеет смысл! –

+0

@maxihatop: - Обновлен мой ответ тем, на что вы можете указывать !!! :) –

0

Это мой ответ - возвращается случайное значение в [min, max), за исключением «except».

int myrand(int min, int max, int except) { 
    int rc; 
    do { 
     rc = min + rand() % (max - min); 
    } while(rc == except); 
    return rc; 
} 
+0

Я думаю, что 'rc = min + rand()% (max - min)' не будет печатать значение 'max'. – haccks

+0

Да, ты прав. Я сказал выше: [мин, макс.]; Это стандартная математическая нотация: [= include,) = исключение. – maxihatop

+0

Я пропустил это :) – haccks

Смежные вопросы