2013-09-10 6 views
11

Однажды мой учитель научил меня использовать функцию randomize() и random() для генерации псевдослучайных чисел в C++ Builder. Теперь я предпочитаю работать в VS 2012, но когда я пытался использовать эти функции, там говорится, что «идентификатор не найден», даже когда я добавил #include <stdlib.h>. По прошествии некоторого времени в Googling я обнаружил, что есть также функции rand() и srand(). В чем разница между ними и какой из них лучше использовать?Какая разница между функциями rand() и random()?

+2

вы должны использовать [случайный заголовок] (http://en.cppreference.com/w/cpp/numeric/random), так как [использование rand() считается вредным] (http: //channel9.msdn. com/Events/GoingNative/2013/rand-Considered-Harmful) –

+3

«считается вредным» является субъективной мерой. Это зависит от того, что вы делаете. В конце концов, это всего лишь псевдослучайный генератор. –

+2

Это очень дурно, и невозможно доказать какие-либо свойства о распределении (что, вероятно, важно, если вы генерируете случайные числа в первую очередь.) – bstamour

ответ

26

randomize() и random() не входят в стандартную библиотеку. Возможно, ваш учитель написал функции с этими именами для использования в вашем классе, или, может быть, вы действительно имеете в виду random() и srandom(), которые являются частью POSIX и недоступны в Windows. rand() и srand() являются частью стандартной библиотеки и будут предоставляться любой стандартной реализацией C++.


Вы должны избегать rand() и srand() и использовать новый 11 <random> C++ библиотека. <random> был добавлен как часть стандарта C++ 11 (и VS2012 его предоставляет).

Видео объясняет, почему: rand() Considered Harmful

  • rand() обычно низкое качество ГСЧ и не подходит для приложений, которым требуется разумный уровень непредсказуемости. <random> предлагает различные двигатели с различными характеристиками, подходящими для разных вариантов использования.

  • Преобразование результатов rand() в номер, который вы можете использовать непосредственно, как правило, зависит от кода, который трудно читать и легко ошибиться, в то время как с помощью <random> распределения легко и производит читаемый код.

  • Общие методы генерации значений в данном распределении с использованием rand() дополнительно уменьшают качество сгенерированных данных. %, как правило, смещает данные, а деление с плавающей запятой все еще создает неравномерные распределения. <random> дистрибутивы более высокого качества, а также более читаемые.

  • rand() опирается на скрытый глобальный ресурс. Среди других проблем это вызывает rand(), чтобы не быть потокобезопасным. Некоторые реализации обеспечивают гарантии безопасности потоков, но это не стандарт. Двигатели, предоставленные <random>, инкапсулируют состояние pRNG как объекты со значениями семантики, что позволяет гибко управлять состоянием.

  • srand() разрешает только ограниченный ассортимент семян. Двигатели в <random> могут быть инициализированы с использованием последовательностей семян, которые позволяют получить максимально возможные данные семян. seed_seq также реализует общую разминку pRNG.


пример использования <random>:

#include <iostream> 
#include <random> 

int main() { 
    // create source of randomness, and initialize it with non-deterministic seed 
    std::random_device r; 
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; 
    std::mt19937 eng{seed}; 

    // a distribution that takes randomness and produces values in specified range 
    std::uniform_int_distribution<> dist(1,6); 

    for (int i=0; i<100; ++i) { 
    std::cout << dist(eng) << '\n'; 
    } 
} 
+2

Все вещи относительные, и в зависимости от того, что вы делаете, 'rand()' может быть в значительной степени достаточным. (Кроме того, почему все эти презентации как видео? C++ в основном используется профессионально, а это значит, что мы не можем активировать звук на наших машинах и не можем смотреть видео.) –

+0

Ну, это представление идет прямо в мусорный ящик для создания такие нелепые утверждения, как «rand()« считаются вредными ». Ложь. 'rand()' не считается вредным и никогда не будет. Проблема здесь заключается в простом выборе правильного инструмента для работы. 'rand()' является прекрасно используемой функцией, если вы понимаете, что это такое. – AnT

+1

@JamesKanze Наушники удобны в офисе. Есть, вероятно, и приличные текстовые ресурсы, но я не знаю ни одного из них. Даже если качество и неравномерность не являются предметом озабоченности, все же нужно предпочесть '' просто для удобства чтения. – bames53

3

Похоже, вы использовали функции C-стиля, хотя ваш вопрос обозначен C++. Кроме того, stdlib.h является файлом заголовка из стандартной библиотеки C. Нет таких функций: random() и randomize() в стандартной библиотеке C. В стандартной библиотеке C есть rand() и srand().

Если вы использовали random() или что-то в этом роде через stdlib.h, возможно, это было некое стандартное расширение библиотеки в компиляторе Borland.

Итак, если вы хотите придерживаться стандартных функций C-стиля, это будет, опять же, rand() и srand(). Но если вы пишете на C++, у вас могут быть лучшие (и более подходящие) варианты в стандартной библиотеке C++.

+0

Означает ли это, что random() и randomize() являются только включен в компилятор C++ Borland? – Sunrise

+0

@Sunrise: Это то, что нестандартное означает, да. –

2

srand() это библиотека реализации C Стандарт для посева (псевдо) генератор случайных чисел. rand() - генератор случайных чисел (псевдо) в стандартной библиотеке C.

C++ реализован новую (псевдо) генератор случайных чисел в файле <random> заголовка, который имеет множество различных двигателей для использования: http://en.cppreference.com/w/cpp/numeric/random

0

Я не знаком с randomize() и random(), но они не являются частью стандартная библиотека. Вам следует избегать использования rand(). Это видео объясняет, почему using rand() is considered harmful.

Вы должны использовать random header введенный в C++, вот пример с использованием как std::uniform_real_distribution и std::uniform_int_distribution:

#include <iostream> 
#include <random> 

int main() 
{ 
    std::random_device rd; 

    std::mt19937 e2(rd()); 

    std::uniform_int_distribution<> dist(1, 6); 
    std::uniform_real_distribution<> distReal(1, 6); 

    for(int i = 0 ; i < 10; ++i) 
    { 
     std::cout << dist(e2) << ","; 
    } 
    std::cout << std::endl ; 

    for(int i = 0 ; i < 10; ++i) 
    { 
     std::cout << distReal(e2) << ","; 
    } 
    std::cout << std::endl ; 

    return 0 ; 
} 
4

Хотя есть (очевидно, выше) люди, которые будут утверждать с религиозным рвением что rand() является плохим и random() не является, выясняется, что ваш пробег может отличаться. Вот ответ gcc на вопрос «Какая разница ...», как указано в gcc-версии stdlib.h (выделено мной):

/* Это те функции, которые на самом деле что-то делают. random', srandom ', initstate' and Функции setstate - это функции из BSD Unices. Функции rand' and srand требуются стандартом ANSI. Мы предоставляем оба интерфейса одному генератору случайных чисел./ / Возвращает случайное длинное целое число от 0 до RAND_MAX включительно. */

-2

Это работа вокруг случайных чисел, созданных вне C++.

Это оригинальная программа на C, скопированная с "http://www.programmingsimplified.com/" Эта программа не запускается, потому что "temp1 = 1 + random (588);" "temp2 = 1 + random (380);" заявления не работают. «random» не является функцией graphics.h, conio.h или stdlib.h. . Не работает, если вы включили random.h. Ниже приведено описание рабочего процесса для случайной функции.

#include<graphics.h> 
#include<conio.h> 
#include<stdlib.h> 
main() 
{ 
    int gd = DETECT, gm, area, temp1, temp2, left = 25, top = 75; 
    void *p; 
    initgraph(&gd,&gm,"C:\\TC\\BGI"); 

    setcolor(YELLOW); 
    circle(50,100,25); 
    setfillstyle(SOLID_FILL,YELLOW); 
    floodfill(50,100,YELLOW); 

    setcolor(BLACK); 
    setfillstyle(SOLID_FILL,BLACK); 
    fillellipse(44,85,2,6); 
    fillellipse(56,85,2,6); 

    ellipse(50,100,205,335,20,9); 
    ellipse(50,100,205,335,20,10); 
    ellipse(50,100,205,335,20,11); 

    area = imagesize(left, top, left + 50, top + 50); 
    p = malloc(area); 

    setcolor(WHITE); 
    settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2); 
    outtextxy(155,451,"Smiling Face Animation"); 

    setcolor(BLUE); 
    rectangle(0,0,639,449); 

    while(!kbhit()) 
    { 
     temp1 = 1 + random (588); 
     temp2 = 1 + random (380); 

     getimage(left, top, left + 50, top + 50, p); 
     putimage(left, top, p, XOR_PUT); 
     putimage(temp1 , temp2, p, XOR_PUT); 
     delay(100); 
     left = temp1; 
     top = temp2; 
    } 

    getch(); 
    closegraph(); 
    return 0; 
} 

Случайные числа генерируются с помощью простого макроса MS Excel, перечисленных здесь:

Sub Macro1() 
Dim i 
For i = 1 To 400 
Randomize 

Range("a" & i) = Int(Rnd * 588) + 1 
Range("b" & i) = Int(Rnd * 380) + 1 

Next i 
End Sub 

Это создает 2 столбца случайных чисел.Каждый столбец копируется и вставляется в собственный файл * .txt, т. Е. Rnd1.txt и rnd2.txt, и помещается в каталог, где они могут быть , доступ к которым осуществляется с помощью следующей программы C++. Подставьте «c: \ PATH \ rnd1.txt» и «C: \ PATH \ rnd2.txt» с правильным путем.

#include<iostream> 
#include<fstream> 
#include<graphics.h> 

using namespace std; 
int i,j,k; 
int main(int argc, char** argv) { 
    std::ifstream infile1; 
    infile1.open("c:\\PATH\\rnd1.txt",ios::in); 
    ifstream infile2; 
    infile2.open("c:\\PATH\\rnd2.txt",ios::in); 
    int gd = DETECT, gm, area, temp1, temp2, left = 25, top = 75; 
    void *p; 
    initgraph(&gd,&gm,"C:\\TC\\BGI"); 

    setcolor(YELLOW); 
    circle(50,100,25); 
    setfillstyle(SOLID_FILL,YELLOW); 
    floodfill(50,100,YELLOW); 

    setcolor(BLACK); 
    setfillstyle(SOLID_FILL,BLACK); 
    fillellipse(44,85,2,6); 
    fillellipse(56,85,2,6); 

    ellipse(50,100,205,335,20,9); 
    ellipse(50,100,205,335,20,10); 
    ellipse(50,100,205,335,20,11); 

    area = imagesize(left, top, left + 50, top + 50); 
    p = malloc(area); 

    setcolor(WHITE); 
    settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2); 
    outtextxy(155,451,"Smiling Face Animation "); 

    setcolor(BLUE); 
    rectangle(0,0,639,449); 

    while(!kbhit()) 
    { 
     infile1 >> j; 
     temp1 = j; 
     infile2 >> k; 
     temp2 = k; 
     if(infile2.eof()) { 
     closegraph(); 
     void close(); 
     return 0; 
     }     
     getimage(left, top, left + 50, top + 50, p); 
     putimage(left, top, p, XOR_PUT); 
     putimage(temp1 , temp2, p, XOR_PUT); 
     delay(100); 
     left = temp1; 
     top = temp2; 
     } 

     } 

Эта программа будет работать в течение 40 секунд, а затем прекратится.

+0

Использование Excel для генерации случайных чисел для приложения C++ ... bleh. Намного лучше найти достойную библиотеку, если вы не хотите использовать «встроенные» параметры. [обязательная ссылка xkcd] (http://xkcd.com/763) – Baldrickk

+0

graphics.h, conio.h и ... EXEL? Шутки в сторону? – YoYoYonnY

2

Функции rand() и random() либо определяются POSIX с по меньшей мере POSIX.1-2001.

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

Когда это возможно, random() не страдает от этой проблемы.

В добавлении, современная версия rand() использует тот же генератор случайных чисел, что и random(). Таким образом, rand() может быть правильным, но он не гарантируется.

Итак, всегда используйте random() вместо rand(). Если random() недоступно в вашей операционной системе, попросите разработчиков операционной системы предоставить более новую реализацию API стандартов (стандарт 2001 года уже достаточно велик, чтобы ожидать, что какая-либо система предоставит его).

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