Форум программистов, компьютерный форум CyberForum.ru

Случайные числа - C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
19.08.2011, 13:14     Случайные числа #1
Всем привет! Мне нужно сгенерировать действительное случайное число в диапазоне от нуля до 1. Читал вот это: http://www.cyberforum.ru/cpp-beginners/thread44753.html, но там говорится про целые числа...
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.08.2011, 13:14     Случайные числа
Посмотрите здесь:

C++ случайные числа в с++
C++ случайные числа
Случайные числа C++
C++ случайные числа
Случайные числа C++
C++ Случайные числа
Случайные числа в C++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Olga_
 Аватар для Olga_
840 / 182 / 16
Регистрация: 01.08.2011
Сообщений: 502
19.08.2011, 13:19     Случайные числа #2
Так разделите сгенерированное число на длину диапазона, делов то
Например, если ваше число из промежутка от A до B (включительно), то полученное число разделите на (B-A+1)
silent_1991
Эксперт C++
4947 / 3023 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.08.2011, 13:19     Случайные числа #3
C++
1
double rand_value = static_cast< double >(rand()) / RAND_MAX;
lemegeton
 Аватар для lemegeton
2913 / 1342 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.08.2011, 13:23     Случайные числа #4
C
1
float n = (rand() % 10000) / 10000.;
Вместо десяти тысяч подставляй любые числа для получения нужной точности.

C
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
 
int main(int argc, char *argv[]) {
  srand(time(NULL));
  int N = 5; // пять знаков после запятой.
  printf("%.10f\n", (rand() % (int)pow(10, N)) / pow(10, N));
 
  return 0;
}
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
19.08.2011, 13:37  [ТС]     Случайные числа #5
Цитата Сообщение от lemegeton Посмотреть сообщение
C
1
float n = (rand() % 10000) / 10000.;
Вместо десяти тысяч подставляй любые числа для получения нужной точности.

C
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
 
int main(int argc, char *argv[]) {
  srand(time(NULL));
  int N = 5; // пять знаков после запятой.
  printf("%.10f\n", (rand() % (int)pow(10, N)) / pow(10, N));
 
  return 0;
}
Это не подойдёт, потому что я посмотрел RAND_MAX = 32768. То есть максимальная точность, которую можно получить это 1/32768.
Olga_
 Аватар для Olga_
840 / 182 / 16
Регистрация: 01.08.2011
Сообщений: 502
19.08.2011, 13:40     Случайные числа #6
Можно так, если вам одно число надо:

C++
1
    (double)time(NULL)/ULONG_MAX;
grizlik78
Эксперт С++
 Аватар для grizlik78
1887 / 1419 / 103
Регистрация: 29.05.2011
Сообщений: 2,967
19.08.2011, 13:45     Случайные числа #7
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Это не подойдёт, потому что я посмотрел RAND_MAX = 32768. То есть максимальная точность, которую можно получить это 1/32768.
Возьми генератор, у которого диапазон больше.
В библиотеке GSL широкий выбор генераторов, я бы их использовал.
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
19.08.2011, 14:21  [ТС]     Случайные числа #8
А как её подключить, и где скачать?
grizlik78
Эксперт С++
 Аватар для grizlik78
1887 / 1419 / 103
Регистрация: 29.05.2011
Сообщений: 2,967
19.08.2011, 15:21     Случайные числа #9
Проще всего её использовать в Linux, конечно же.
http://www.gnu.org/software/gsl/
Но и для Windows видел скомпилированные варианты. Правда здесь могут быть и сложности для разных компиляторов.
Иногда недостатком может быть её лицензия — GPL

Добавлено через 29 минут
В принципе можно попробовать скомбинировать случайное число из нескольких
Например так должны получаться числа из диапазона [0, 1) с разрешением примерно в одну миллиардную.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
 
#define RND_BITS 15
#if (1ul << RND_BITS) - 1 != RAND_MAX
#error Wrong value of RND_BITS
#endif
 
#define DBL_SIZE_RAND (( ((long)rand() << RND_BITS) | rand() ) / (double)(1ul << (2*RND_BITS)))
 
int main(void)
{
    double rnd_val;
    srand((unsigned)(time(NULL)));
 
    rnd_val = DBL_SIZE_RAND;
 
    printf("rnd_val: %g\n", rnd_val);
    
    return 0;
}
Но раз требования к ГПСЧ выше, чем к обычному rand(), то я бы всё-таки смотрел на альтернативные генераторы. Если есть сложности с GSL, могу попробовать помочь.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9384 / 5434 / 916
Регистрация: 25.07.2009
Сообщений: 10,428
19.08.2011, 15:38     Случайные числа #10
Не мудрствуя лукаво (0; 1]
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
    
double drand(void){
    double d = (double)(rand() + 1) / (double)(rand() + 1);
    return d / pow(10.0, ceil(log10(d)));
}
 
int main(void){
    int i;
    
    srand(time(NULL));
    for ( i = 0; i < 10; ++i )
        printf("%f\n", drand());
        
    return 0;
}
grizlik78
Эксперт С++
 Аватар для grizlik78
1887 / 1419 / 103
Регистрация: 29.05.2011
Сообщений: 2,967
19.08.2011, 15:44     Случайные числа #11
Цитата Сообщение от easybudda Посмотреть сообщение
(double)(rand() + 1)
По-моему в этом месте программа сломается, если вдруг RAND_MAX == INT_MAX
Я короче записываю обычно: (rand() + 1.0), хотя и ещё раз к даблу привести не повредит.

Добавлено через 2 минуты
easybudda, а там равномерное распределение получается? Что-то как-то не очевидно.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9384 / 5434 / 916
Регистрация: 25.07.2009
Сообщений: 10,428
19.08.2011, 15:48     Случайные числа #12
Цитата Сообщение от grizlik78 Посмотреть сообщение
По-моему в этом месте программа сломается, если вдруг RAND_MAX == INT_MAX
Теоритически может, но это какой-то маргинальный случай, обычно там
C
1
#define RAND_MAX    0x7FFF
Если так всего бояться, то можно
C
1
double d = ((double)rand() + 0.1) / ((double)rand() + 0.1);
но я бы не заморачивался...

Добавлено через 1 минуту
Цитата Сообщение от grizlik78 Посмотреть сообщение
а там равномерное распределение получается?
Да чёрт его знает... Можно изменить цикл
C
1
for ( i = 0; i < 100500; ++i )
результат в файл и изучать, что получится. На глаз вроде ничё так последовательности...
grizlik78
Эксперт С++
 Аватар для grizlik78
1887 / 1419 / 103
Регистрация: 29.05.2011
Сообщений: 2,967
19.08.2011, 15:56     Случайные числа #13
Цитата Сообщение от easybudda Посмотреть сообщение
Теоритически может, но это какой-то маргинальный случай, обычно там
Ну значит у меня маргинальный GCC
$ grep RAND_MAX -B1 /usr/include/stdlib.h
/* The largest number rand will return (same as INT_MAX). */
#define RAND_MAX 2147483647
Добавлено через 6 минут
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <assert.h>
 
double drand(void){
    double d = (double)(rand() + 1) / (double)(rand() + 1);
    return d / pow(10.0, ceil(log10(d)));
}
 
#define N 10
 
int main(void){
    int i;
    int cnt[N];
    for ( i = 0; i < N; ++i )
        cnt[i] = 0;
 
    srand(time(NULL));
    for ( i = 0; i < 1000*N; ++i )
    {
        unsigned idx = N*(1.0 - drand());
        assert(idx < N);
        ++cnt[idx];
    }
    for ( i = 0; i < N; ++i )                
        printf("cnt[%d] = %d\n", i, cnt[i]);
    
    return 0;
}
Результат:
cnt[0] = 621
cnt[1] = 607
cnt[2] = 671
cnt[3] = 733
cnt[4] = 707
cnt[5] = 832
cnt[6] = 1027
cnt[7] = 1457
cnt[8] = 3345
cnt[9] = 0
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9384 / 5434 / 916
Регистрация: 25.07.2009
Сообщений: 10,428
19.08.2011, 16:00     Случайные числа #14
Цитата Сообщение от grizlik78 Посмотреть сообщение
Ну значит у меня маргинальный GCC
Да, это я что-то погорячился... Ну тогда ((double)rand() + 0.1). Так вроде бы не должно обнуляться...

200 чисел
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
    
double drand(void){
    double d = ((double)rand() + 0.1) / ((double)(rand() + 0.1));
    return d / pow(10.0, ceil(log10(d)));
}
 
int main(void){
    int i, j;
    
    srand(time(NULL));
    for ( i = 1; i < 201; ++i )
        printf("%.8f%s", drand(), ( i % 6 ) ? "  " : "\n");
        
    return 0;
}

Результат
Код
C:\c_cpp\numbers>gcc -o drand drand.c

C:\c_cpp\numbers>drand
0.13408709  0.45438382  0.20997227  0.28582088  0.47934566  0.70207744
0.80142783  0.11285232  0.10017294  0.32219875  0.14201281  0.21939556
0.72064488  0.71223923  0.66613015  0.83083992  0.34304319  0.47746109
0.12242242  0.52487659  0.94874149  0.25269225  0.22163864  0.63875379
0.22708711  0.12037155  0.38233554  0.21128308  0.83689846  0.99518291
0.32645971  0.17803438  0.33741471  0.43446061  0.10399398  0.33922063
0.30402586  0.72990869  0.38214058  0.12692512  0.37016251  0.16352609
0.42100462  0.97823775  0.23424048  0.42015095  0.44437679  0.12353194
0.14431375  0.60560665  0.11781796  0.13394005  0.44395224  0.62175893
0.81992461  0.83912069  0.26671849  0.65803503  0.44179500  0.35539157
0.48121330  0.54772206  0.14353008  0.52777368  0.15835940  0.23142768
0.16930682  0.12201771  0.70176335  0.13181393  0.19406651  0.98627138
0.14164158  0.71810773  0.26883522  0.28677665  0.18602492  0.12826084
0.89619636  0.69113789  0.11136309  0.32574622  0.11203060  0.93134284
0.94115108  0.23962475  0.16901496  0.12735332  0.31190313  0.21171270
0.13574662  0.69101045  0.45534408  0.29591413  0.38996416  0.10465808
0.14764675  0.84053127  0.24983965  0.38221488  0.16014635  0.91472573
0.11378074  0.36289655  0.62868948  0.11311313  0.39656151  0.97624394
0.10490198  0.42158518  0.14162824  0.47222358  0.11180244  0.13253781
0.65163090  0.15149216  0.77111881  0.10692751  0.22192583  0.79310515
0.10261053  0.83233248  0.11246742  0.66353418  0.57380631  0.14257267
0.12364680  0.10157202  0.43665649  0.66699525  0.40242673  0.78446027
0.17287892  0.35278461  0.30718313  0.71415941  0.85101637  0.10954653
0.90804842  0.22999891  0.94726724  0.69922107  0.57407012  0.73058384
0.45122386  0.93527746  0.23106121  0.44087031  0.49882093  0.64576453
0.56784913  0.12812567  0.42992645  0.37501747  0.22982386  0.94057448
0.76696871  0.39571402  0.62805393  0.84396103  0.91289743  0.11651659
0.27112123  0.21773571  0.95695310  0.14058905  0.27447721  0.25067962
0.71775141  0.33639818  0.10052040  0.66479427  0.17353157  0.22751950
0.81624253  0.11165994  0.65255280  0.29873404  0.23138585  0.77620395
0.13899751  0.12649695  0.11693862  0.31505214  0.17811168  0.26604305
0.37800195  0.81811912  0.12342671  0.16791423  0.28091345  0.18186519
0.64902356  0.16578954  0.11262510  0.17164544  0.17303484  0.13305711
0.35952225  0.15212247
C:\c_cpp\numbers>
далеко, конечно, от идеала, но в принципе в не особо придирчивых приложениях вполне можно пользоваться. За то просто...

Не по теме:

Подошло бы для задания вероятности выйгрыша в одноруком бандите - как-то оно к 0.1 ближе, чем к 1 получается...

grizlik78
Эксперт С++
 Аватар для grizlik78
1887 / 1419 / 103
Регистрация: 29.05.2011
Сообщений: 2,967
19.08.2011, 16:01     Случайные числа #15
Ну 1.0 по моему ничем не хуже (хотя, наверное, и не лучше)
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
20.08.2011, 20:12  [ТС]     Случайные числа #16
Вот так можно сгенерировать случайные числа с большой точностью:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Test.cpp : Defines the entry point for the console application.
 
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <time.h>
using namespace std;
 
#define fl float
#define du double
#define ld long double
#define si short int
#define li long int
#define usi unsigned short int
#define uli unsigned long int
#define uint unsigned int
 
inline fl randf()
{
    fl rndM=(fl)RAND_MAX;
    fl res=0;
    for (fl rests=1.f-1.f/rndM;rests>0;rests/=rndM)
    {
        res+=((fl)rand()/rndM)*rests;
    }
    return res;
}
 
int _tmain(int argc, _TCHAR* argv[])
{   
    srand((uint)time(NULL));
    si kol;
    cin>>kol;
    for (;kol>0;kol--)
    {
        cout<<randf()<<'\n';
        system("pause");
    }
    system("pause");
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.08.2011, 20:39     Случайные числа
Еще ссылки по теме:

случайные числа C++
C++ Случайные числа
C++ Случайные числа
Случайные числа от 1 до 9 C++
C++ Случайные числа

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
grizlik78
Эксперт С++
 Аватар для grizlik78
1887 / 1419 / 103
Регистрация: 29.05.2011
Сообщений: 2,967
20.08.2011, 20:39     Случайные числа #17
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Вот так можно сгенерировать случайные числа с большой точностью:
Вряд ли термин точность хорошо подходит к случайным числам
По сути это тот же подход, что и использованный мной в #9, только с другой стороны и гораздо хитрее
Только всё-равно хочется предупредить — несмотря на то, что два случайных числа теперь могут получиться гораздо ближе друг к другу, нежели при простом делении на RAND_MAX, тем не менее разнообразие этих чисел может оказаться недостаточным из-за ограниченного внутреннего состояния ГПСЧ. Так что получаемые числа всё-равно надо проверять на удовлетворение неким требованиям. А для получения чисел с достаточным разрешением желательно использовать генераторы с по возможности большим размером внутреннего состояния.
Yandex
Объявления
20.08.2011, 20:39     Случайные числа
Ответ Создать тему
Опции темы

Текущее время: 07:09. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru