Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Как сгенерировать случайное число на всем диапазоне значений int? (http://forum.oszone.net/showthread.php?t=141361)

Michael 29-05-2009 13:50 1130249

Как сгенерировать случайное число на всем диапазоне значений int?
 
Добрый день.
Необходимо сгенерировать одномерный массив случайных чисел в диапазоне от INT_MIN до INT_MAX. С генерацией массива проблем нет, а как получить случайное число на всем диапазоне значений целочисленного типа int (от INT_MIN до INT_MAX)?
Спасибо

Coutty 29-05-2009 16:59 1130383

Генерируете случайное число с плавающей точкой от 0 до 1 стандартным способом. Умножаете на (INT_MAX минус INT_MIN), округляете и прибавляете INT_MIN.

Это первое, что приходит в голову. Возможно, есть специальная функция.

P.S. Похоже, я немного неверно понял задание. Алгоритм был написан для генерации числа, скажем от 100 до 500. А если от 0 до "условно 1000", то просто произвольное от 0 до 1 умножить на 1000.

Второе дополнение: если диапазон от -1000 до 1000, то создаётся число от 0 до 1, умножается на тысячу и на "случайный знак". Правда здесь дополнительное ветвление появляется... Что-то вроде этого:
rand() * 1000 * ( (rand() >= 0.5) ? 1 : -1 )

Pliomera 29-05-2009 20:29 1130549

Цитата:

Цитата Coutty
если диапазон от -1000 до 1000, то создаётся число от 0 до 1, умножается на тысячу и на "случайный знак". Правда здесь дополнительное ветвление появляется... »

rand() * 2000 - 1000 :)

PS. В С/С++ ни ухом ни рылом...

Coutty 29-05-2009 20:33 1130553

Цитата:

Цитата Pliomera
rand() * 2000 - 1000 »

Это понятно. А если использовать INT_MAX вместо тысячи? Тогда числа "2000" не будет, т.к. оно выходит за границы диапазона.
Я тоже С/С++ не знаю, но не суть :)

Drongo 30-05-2009 09:49 1130790

В общем есть кое-какая идея, почти сумасбродная и имеющая некий изврат, :whitevoid: но вполне работоспособная при правильном подходе. Изложу суть.

У нас INT_MAX = 2 147 483 647 (в числе 10 цифр и не больше). Используем несколько масивов

Код:

...
 int array1[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Единицы
 int array2[10] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90}; // Десятки
 int array3[10] = {0, 100, 200, 300, 400, 500, 600, 700, 800, 900}; // Сотни
 int array4[10] = {0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000}; // Тысячи
 int array5[10] = {0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000}; // Десятки тысяч
 int array6[10] = {0, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000}; // Сотни тысяч
 int array7[10] = {0, 1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000}; // Миллион
 int array8[10] = {0, 10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000}; // Десятки миллионов
 int array9[10] = {0, 100000000}; // Сотни миллионов. Потому что в значении 2 147 483 647. Максимальное.
 int array10[10] = {0, 100000000, 200000000}; // Миллиард. Потому что в значении 2 147 483 647. Максимальное.
 int array_rand[size] = {0}; // Массив куда будем записывать числа (от INT_MIN до INT_MAX)

 int index1,
    index2,
    index3,
    index4,
    index5,
    index6,
    index7,
    index8,
    index9,
    index10,
    SumNumber;

Далее используем генерацию случайных чисел от '0' до '9'

Код:

#include <stdlib.h>
#include <ctime.h>
using std::time;

...

  srand(time(0));

  for(int i = 0; i < size; i++){
      index1 = rand() % 9; // Значения от '0' до '9' Всего 10 значений. Для индекса массива.
      index2 = rand() % 9;
      index3 = rand() % 9;
      index4 = rand() % 9;
      index5 = rand() % 9;
      index6 = rand() % 9;
      index7 = rand() % 9;
      index8 = rand() % 9;
      index9 = rand() % 1;
      index10 = rand() % 2;

...
  // Проверяем, чтобы 2 147 483 647 не вышел за диапазон значения
  if(index10 == 2){
      // Проверяем, чтобы 2 147 483 647 не вышел за диапазон значения.
      if(index9 == 1){
          // Выполняем суммирование только для этих случаев
          SumNumber = array10[index10] + array9[index9] + array8[index8] ... + ... array2[index2] + array1[index1];
        }
    }

....
  // В итоге и правильном алгоритме, мы получаем
  SumNumber = array10[index10] + array9[index9] + array8[index8] ... + ... array2[index2] + array1[index1];
  array_rand[i] = SumNumber;
  }

А чтобы отрицательное получить, ну, ещё один рандом прикрутить, с диапазоном значений от '0' до '1', если ноль - значит выполняем положительные числа, если единица - ставим к полученому числу - "—". Будет отрицательное.

В тех местах где я выделил зелёным цветом, слегка запутался, так как в числе 2 147 483 647, может быть и так - 2 047 483 647. Но пока ничего не могу придумать. :durak:

Michael 31-05-2009 12:42 1131557

Спасибо - идея понятна. Вот только с реализацией возник вопрос.
Стандартный int rand(void) возвращает случайное целое число в диапазоне от 0 до RAND_MAX, где RAND_MAX=32767. Если получать случайное число в интервале от 0 до 1 вот таким образом - double(rand())/RAND_MAX, то идеологически это будет верно?

Coutty 31-05-2009 13:00 1131568

Вполне. Можно сразу умножать на (INT_MAX/RAND_MAX). Если часто используется генерация, то сохраните это число как константу.

Michael 31-05-2009 17:06 1131677

А как часто надо проводить инициализацию генератора случайных силел - srand(time(0))? Один раз или каждый раз перед использованием rand()?

Drongo 31-05-2009 18:52 1131745

Цитата:

Цитата Michael
А как часто надо проводить инициализацию генератора случайных силел - srand(time(0))? Один раз или каждый раз перед использованием rand()? »

Достаточно одного раза.

pva 01-06-2009 07:54 1132014

чему в вашей системе равны INT_MIN и INT_MAX?
Цитата:

Цитата Borland RTL Help
Syntax

#include <stdlib.h>
int rand(void);

Description

Random number generator.

rand uses a multiplicative congruential random number generator with period 2 to the 32nd power to return successive pseudorandom numbers in the range from 0 to RAND_MAX. The symbolic constant RAND_MAX is defined in stdlib.h.

stdlib.h:
Код:

/* Maximum value returned by "rand" function
*/
#define RAND_MAX  0x7FFFU

Используем идею Drongo»
, только в 2-ичной системе, и представление 32-разрядного int в памяти:
Код:

  int big_rand = (rand() << 30) | (rand() << 15) | rand();

Drongo 01-06-2009 18:48 1132456

Цитата:

Цитата Michael
Спасибо - идея понятна. Вот только с реализацией возник вопрос. »

Если это вопрос в мою сторону, то там и реализации как таковой нет, объеденить две написаные части и всё. Пример ниже.

pva, Я правильно понял, что ваш код, всего одна строка
Цитата:

Цитата pva
Код:

int big_rand = (rand() << 30) | (rand() << 15) | rand();
»

полноценно заменяет мой вариант ниже? Я проверил, работает зашибенно. :up:
1. Решение от pva

Код:

// Генерация случайных значений
// от INT_MIN = -2 147 483 647
// до INT_MAX = 2 147 483 647
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
#include <conio.h>
#include <stdlib.h>
#include <ctime.h>
using std::time;

int main()
{
  int SumNumber;
  srand(time(0));
  for(int i = 0; i < 1000; i++){
    int big_rand = (rand() << 30) | (rand() << 15) | rand();
    cout<<"SumNumber = "<<big_rand<<endl;
  }
  //cin>>SumNumber;
  getch();

 return 0;
}
//---------------------------------------------------------------------------


2. Моё решение, от коментария № 5, для сравнения

Код:

// Генерация случайных значений
// от INT_MIN = -2 147 483 647
// до INT_MAX = 2 147 483 647
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
#include <conio.h>
#include <stdlib.h>
#include <ctime.h>
using std::time;

int main()
{
  const int size = 10;
  const int arrayRandSize = 1000;

  int array1[size] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Единицы
  int array2[size] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90}; // Десятки
  int array3[size] = {0, 100, 200, 300, 400, 500, 600, 700, 800, 900}; // Сотни
  int array4[size] = {0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000}; // Тысячи
  int array5[size] = {0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000}; // Десятки тысяч
  int array6[size] = {0, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000}; // Сотни тысяч
  int array7[size] = {0, 1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000}; // Миллион
  int array8[size] = {0, 10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000}; // Десятки миллионов
  int array9[size] = {0, 100000000}; // Сотни миллионов. Потому что в значении 2 147 483 647. Максимальное.
  int array10[size] = {0, 1000000000, 2000000000}; // Миллиард. Потому что в значении 2 147 483 647. Максимальное.
  int array_rand[arrayRandSize] = {0}; // Массив куда будем записывать числа (от INT_MIN до INT_MAX)

  int index1, index2, index3, index4, index5,
      index6, index7, index8, index9, index10,
      SumNumber;

  srand(time(0));

  for(int i = 0; i < arrayRandSize; i++){
    index9 = rand() % 1;
    index10 = rand() % 2;

  // Проверяем, чтобы 2 147 483 647 не вышел за диапазон значения
  if(index10 == 2 && index9 == 1){
    index1 = rand() % 7; // Значения от '0' до '9' Для индекса массива.
    index2 = rand() % 4;
    index3 = rand() % 6;
    index4 = rand() % 3;
    index5 = rand() % 8;
    index6 = rand() % 4;
    index7 = rand() % 7;
    index8 = rand() % 4;
  }
  else{
    index1 = rand() % 9; // Значения от '0' до '9'. Для индекса массива.
    index2 = rand() % 9;
    index3 = rand() % 9;
    index4 = rand() % 9;
    index5 = rand() % 9;
    index6 = rand() % 9;
    index7 = rand() % 9;
    index8 = rand() % 9;
  }

  // В итоге и правильном алгоритме, мы получаем
  SumNumber = array10[index10] + array9[index9] + array8[index8]
            + array7[index7] + array6[index6] + array5[index5]
            + array4[index4] + array3[index3] + array2[index2]
            + array1[index1];

  // Делаем знаковое число...
  if((1 + rand() % 2) == 1)
    array_rand[i] = SumNumber;
  else
    array_rand[i] = -SumNumber;
   
  //cout<<"SumNumber = "<<SumNumber<<endl;
 }

 for(int i = 0; i < arrayRandSize; i++){
    cout<<"SumNumber = "<<array_rand[i]<<endl;
  }

  //cin>>SumNumber;
  getch();

 return 0;
}
//---------------------------------------------------------------------------


Michael 01-06-2009 20:58 1132540

pva, INT_MAX=2147483647, INT_MIN=-2147483648
Drongo, не, я там про другую реализацию говорил - все вышеописанное опиралось на сгенерированное случайное число в интервале от 0 до 1, а стандартный int rand(void) возвращает случайное целое число в диапазоне от 0 до 32767. И меня интересовало, если получать случайное число в интервале от 0 до 1 следующим образом - double(rand())/RAND_MAX, то будет ли это верно с точки зрения идеологии программирования.

Xucyc 12-01-2011 03:23 1586597

Интересные вы =)))

Код:


rand() % (max- min + 1) + min;


pva 12-01-2011 22:31 1587288

Цитата:

Цитата Michael
INT_MAX=2147483647, INT_MIN=-2147483648 »

всё зависит от представления числа в памяти
Код:

(rand() << 30) | (rand() << 15) | rand();
заполнит все биты 32-битного числа, в т.ч. и старший 31-й бит, который отвечает за знак. Таким образом будет сгенерировано число в диапазоне от -0x80000000 до 0x7fffffff. Если же воспринимать заполненные 32 бита памяти как беззнаковое число, то получится диапазон от 0 до 0xffffffff.

Вариант
Цитата:

Цитата Michael
double(rand())/RAND_MAX*INT_MAX »

не годится по той причине, что он не может сгенерировать число 2. Потому что (0.0/RAND_MAX)*INT_MAX = 0, а (1.0/RAND_MAX)*INT_MAX >32786

так же не годится вариант
Цитата:

Цитата Xucyc
rand() % (max- min + 1) + min; »

в данном случае max- min + 1 = 0

Onyma 04-02-2011 17:08 1604495

Допустим что у нас есть функция rnd(), которая возвращает случайное, равномерно распределённое число в диапазоне от rnd_min до rnd_max.
Наша задача: написать функцию my_rnd(), которая будет возвращать случайное, равномерно распределённое число в диапазоне от my_min до my_max.
Решение:
1. Для начала мы приведём имеющееся у нас случайное число к интервалу [0, 1]:
Код:

  float tmp_rnd = float(rnd() - rnd_min) / (rnd_max - rnd_min);
2. Теперь мы приведём полученное в диапазон [my_min, my_max]:
Код:

  my_int result = tmp_rnd * (my_max - my_min) + my_min;
3. Ну и возвращаем результат:
Код:

  return result;
Здесь предполагается что точности всех применяемых типов хватает для хранения получаемых величин, а так же, что мощность (количество возможных чисел) области значений функции rnd() больше или равно мощности области значений функции my_rnd(); в противном случае некоторые числа из нужного нам диапазона ни когда не будут появляться.

Цитата:

Цитата pva
в данном случае max- min + 1 = 0 »

1. max - min + 1 = 0 => max + 1 = min => min > max. не согласен: всегда max > min.
2. конструкция
Код:

rand() % (max- min + 1) + min;
будет работать при условии, что функция rand() имеет область определения достаточной мощности: RAND_MAX >= (max - min)


Время: 18:41.

Время: 18:41.
© OSzone.net 2001-