Генерація випадкових чисел з поплавком


271

Як генерувати випадкові поплавці в C ++?

Я думав, що можу взяти цілий rand і розділити його на щось, чи це буде достатньо?


2
Це швидше залежить від того, для якого числа ви хочете, і наскільки випадковим. Як правило, rand () дасть 15 біт випадковості, але поплавці мають 23-бітну точність, тому воно пропустить деякі значення.
Піт Кіркхем,

1
Я оновив свою відповідь, щоб включити всі основні варіанти, і мій вибір, щоб зосередитись на randomзаголовку, доданому в C ++ 11, ще більше підкріплений стандартним документом N3924: Перешкоджаючий rand () на C ++ 14 . Я включаю rand()у свою відповідь здебільшого історичні міркування, але також розумію, що застаріле застосування існує.
Шафік Ягмур

Моя відповідь включає, як уникнути отримання однакових цифр кожного разу із <random>заголовком
Andreas DM

Відповіді:


381

rand()може використовуватися для генерації псевдовипадкових чисел у C ++. У поєднанні з RAND_MAXтрохи математики ви можете генерувати випадкові числа в будь-який обраний вами довільний інтервал. Цього достатньо для навчальних цілей та іграшкових програм. Якщо вам потрібні справді випадкові числа з нормальним розподілом, вам потрібно буде використовувати більш досконалий метод.


Це створить число від 0,0 до 1,0 включно.

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

Це буде генерувати число від 0,0 до деякої довільної float, X:

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

Це створить число від якогось довільного LOдо якогось довільного HI:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

Зауважте, що rand()функцій часто буде недостатньо, якщо вам потрібні справді випадкові числа.


Перш ніж зателефонувати rand(), потрібно спочатку "засіяти" генератор випадкових чисел, зателефонувавши srand(). Це потрібно робити один раз під час запуску програми - не раз під час дзвінка rand(). Це часто робиться так:

srand (static_cast <unsigned> (time(0)));

Для того, щоб зателефонувати randабо srandпотрібно #include <cstdlib>.

Для того, щоб зателефонувати time, ви повинні #include <ctime>.


22
Не забувайте спочатку сіяти!
Клаїм

14
Найкраще зазначити, що обидва межі включно.
dmckee --- кошеня колишнього модератора

14
Ця відповідь вводить в оману. Це висвітлювалося на Going Native 2013 минулого тижня; rand () Вважається шкідливим, channel9.msdn.com/Events/GoingNative/2013/… для дуже детального пояснення.
Аде Міллер

14
Я не розумію, чому так багато людей підтримали цю відповідь. Це математично неправильно. RAND_MAX - це дуже мала кількість (зазвичай 2 ^ 16). Це означає, що з 23 бітів плаваючої точки ви робите лише 15 випадкових. Іншим буде, мабуть, нуль. Ви дійсно отримаєте випадкові числа при рівномірному розподілі, але з низькою точністю. Наприклад, ваш випадковий генератор може генерувати 0,00001 та 0,00002, але не може генерувати 0,000017. Таким чином, ви маєте рівномірний розподіл, але з низькою точністю (в 256 разів менше точності, ніж фактична плаваюча точка).
DanielHsH

10
@DanielHsH: ОП спеціально запитала, яку механіку можна використовувати для генерації випадкових поплавків rand(). Це питання, і моя відповідь, було спеціально зосереджено на вивченні основ, і його не хвилювало висока ступінь точності. Ви повинні навчитися ходити, перш ніж ви зможете навчитися бігати.
Джон Дайблінг

137

C ++ 11 дає багато нових варіантів random. Канонічним документом на цю тему буде N3551, Генерація випадкових чисел у C ++ 11

Щоб зрозуміти, чому використання rand()може бути проблематичним, див. Rand () Розглянуті шкідливі презентаційні матеріали Стефана Т. Лававей, подані під час події GoingNative 2013 . Слайди - у коментарях, але ось пряме посилання .

Я також охоплюю boostта використовую, randоскільки застарілий код все ще може потребувати його підтримки.

Наведений нижче приклад переганяється з сайту cppreference і використовує двигун std :: mersenne_twister_engine та std :: uniform_real_distribution, який генерує числа в [0,10)інтервалі, з іншими коментованими движками та дистрибутивами ( див. Це в прямому ефірі ):

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    //
    // Distribtuions
    //
    std::uniform_real_distribution<> dist(0, 10);
    //std::normal_distribution<> dist(2, 2);
    //std::student_t_distribution<> dist(5);
    //std::poisson_distribution<> dist(2);
    //std::extreme_value_distribution<> dist(0,2);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(e2))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

вихід буде аналогічний наступному:

0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****

Вихід буде змінюватися залежно від того, який розподіл ви вибрали, тому, якщо ми вирішили перейти з std :: normal_distribution зі значенням як 2для середнього, так і для stddev, наприклад, dist(2, 2)натомість вихід буде подібний до цього ( дивіться його в прямому ефірі ):

-6 
-5 
-4 
-3 
-2 **
-1 ****
 0 *******
 1 *********
 2 *********
 3 *******
 4 ****
 5 **
 6 
 7 
 8 
 9 

Далі йде модифікована версія деякого коду, представленого в N3551( див. Його наживо ):

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

std::default_random_engine & global_urng( )
{
    static std::default_random_engine u{};
    return u ;
}

void randomize( )
{
    static std::random_device rd{};
    global_urng().seed( rd() );
}

int main( )
{
  // Manufacture a deck of cards:
  using card = int;
  std::array<card,52> deck{};
  std::iota(deck.begin(), deck.end(), 0);

  randomize( ) ;  

  std::shuffle(deck.begin(), deck.end(), global_urng());
  // Display each card in the shuffled deck:
  auto suit = []( card c ) { return "SHDC"[c / 13]; };
  auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };

  for( card c : deck )
      std::cout << ' ' << rank(c) << suit(c);

   std::cout << std::endl;
}

Результати будуть схожі на:

5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S

Підвищення

Звичайно, Boost.Random - це також завжди варіант, тут я використовую boost :: random :: uniform_real_distribution :

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
    boost::random::mt19937 gen;
    boost::random::uniform_real_distribution<> dist(0, 10);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(gen))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

rand ()

Якщо вам потрібно скористатися, rand()ми можемо перейти до C FAQ для керівництва про те, як я можу генерувати випадкові числа з плаваючою комою? , що в основному дає приклад, аналогічний цьому для генерації інтервалу [0,1):

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

і генерувати випадкове число в діапазоні від [M,N):

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}

1
Ви можете виправити свої randMToNPLS? або зауважте, що це, [M,N]або додайте назад + 1.із вищезазначеного randZeroToOne. -> подумайте назвати це так:randMToN(0.0, 1.0);
BeyelerStudios

1
Також будьте обережні з поділом на нуль на (N-M). Приємний спосіб вирішити цю помилку можна знайти тут: stackoverflow.com/questions/33058848/…
Д-р Беко,

61

Погляньте на Boost.Random . Ви можете зробити щось подібне:

float gen_random_float(float min, float max)
{
    boost::mt19937 rng;
    boost::uniform_real<float> u(min, max);
    boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
    return gen();
}

Пограйте, вам може бути краще передавати один і той же об’єкт mt19937, а не створювати новий кожен раз, але, сподіваємось, вам прийде ідея.


1
uniform_real використовує напіввідкритий інтервал [min, max), що означає, що ви отримаєте мінімальне значення, але ніколи не досягнете максимального значення. Це щось, що варто врахувати, хоча якщо ви об'їдете якийсь спосіб, ви зможете подолати цю проблему.
TehWan

20
Зараз це частина C ++ 11.
Томаш Андрле

@Wolf у практичних програмах шанси потрапити на якесь конкретне значення з плаваючою точкою настільки низькі, що не має значення, включена чи виключена кінцева точка. Якщо вам потрібно , maxале можна використовувати з відкритим кінцем min, ви можете повністю змінити інтервал легко: return min + max - gen();.
Марк Рансом

26

У сучасних умовах c++ви можете використовувати <random>заголовок, який постачається разом c++11.
Щоб отримати випадкові float, ви можете використовувати std::uniform_real_distribution<>.

Ви можете використовувати функцію для генерації чисел, і якщо ви не хочете, щоб цифри постійно були однаковими , встановіть двигун та розподіл static.
Приклад:

float get_random()
{
    static std::default_random_engine e;
    static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
    return dis(e);
}

Ідеально розмістити їх floatу контейнері, наприклад std::vector:

int main()
{
    std::vector<float> nums;
    for (int i{}; i != 5; ++i) // Generate 5 random floats
        nums.emplace_back(get_random());

    for (const auto& i : nums) std::cout << i << " ";
}

Приклад виводу:

0.0518757 0.969106 0.0985112 0.0895674 0.895542

std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1технічно неправильно, 1,0 ніколи не буде генеровано, див. en.cppreference.com/w/cpp/numeric/random/… To create a distribution over the closed interval [a,b], std::nextafter(b, std::numeric_limits<RealType>::max()) may be used as the second parameter.
Troyseph

1
Це має бути прийнята відповідь, це химерно 2020.
Олексій

25

Виклик коду з двома floatзначеннями, код працює в будь-якому діапазоні.

float rand_FloatRange(float a, float b)
{
    return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}

Варто зазначити, що це потенційний випадок використання fmaf()(або поплавкового fma()перевантаження в C ++) у C99 або C ++ 11, що може зберегти більшу точність. Як і в fmaf((float)rand() / RAND_MAX, b - a, a).
Тім Час

22

Якщо ви використовуєте C ++, а не C, то пам’ятайте, що в технічному звіті 1 (TR1) та в чернетці C ++ 0x вони додали засоби для генератора випадкових чисел у файлі заголовка, я вважаю, що він ідентичний Boost. Випадкова бібліотека і, безумовно, більш гнучка і "сучасна", ніж функція бібліотеки С, rand.

Цей синтаксис пропонує можливість вибору генератора (як, наприклад, mersenne twister mt19937), а потім вибору розподілу (нормального, bernoulli, binomial тощо).

Синтаксис такий (безсоромно запозичено з цього сайту ):

  #include <iostream>
  #include <random>

  ...

  std::tr1::mt19937 eng;  // a core engine class 
  std::tr1::normal_distribution<float> dist;     

  for (int i = 0; i < 10; ++i)        
      std::cout << dist(eng) << std::endl;

2
Це тепер у C ++ 11, також dist може бути ініціалізовано зі значеннями min та max.
Етьєнн

Мені здається дивним ставити min та max в ініціалізатор і надавати генератору при отриманні значення - я вважаю за краще, якби це було навпаки, ну добре.
yoyo

6

У деяких системах (Windows з VC на даний момент сприймається), RAND_MAXце смішно мало, я. е. лише 15 біт. Під час ділення RAND_MAXви генеруєте лише мантію з 15 біт замість 23 можливих бітів. Це може бути або не бути проблемою для вас, але ви пропускаєте деякі значення в цьому випадку.

О, щойно помітив, що вже є коментар до цієї проблеми. У будь-якому випадку, ось код, який може вирішити це для вас:

float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);

Не перевірено, але може спрацювати :-)


Що про float r = (float) ((rand () << 9) | rand ()) / RAND_MAX? (також не перевірено)
Пастка

Арг, вибачте, розділення на RAND_MAX не приведе вас нікуди ... вся суть цього трюку полягала в тому, щоб щось було більше, ніж RAND_MAX ... виправлено це і для мене.
Joey

2
Будьте уважні до складання випадкових чисел без теорії ... послідовні виклики rand () можуть бути не повністю незалежними. Підказка: якщо його лінійний генератор конгруентності, слідкуйте за низьким бітом під час послідовних дзвінків: він чергується між 0 і 1.
RBerteig

Я знаю. Для деяких застосувань цього може бути достатньо. Але так, у цьому випадку вам, мабуть, слід скористатися більше, ніж просто два дзвінки. У цій справі немає срібної кулі, ви навіть не можете розраховувати на те, що це LCG. Інші PRNG мають слабкі високі біти. Тут має бути найкраще рішення Boost.
Джої

(nb: Низький біт, що повертається rand в MSVC, не є найнижчим бітом стану RNG. Для 100 rand () дзвінків я отримую наступне: 1100100000111111101010010010011010101110110110111010011111100100000000010100011011000000100101100011. Java використовує 48-розрядний LCG і використовує лише 32 bits LCG, а використовує лише 32 bits зробити це аналогічно)
Joey

4

drand48(3)є стандартним способом POSIX. GLibC також забезпечує версію поворотній, drand48_r(3).

Ця функція була оголошена застарілою в SVID 3, але не було надано адекватної альтернативи, тому IEEE Std 1003.1-2013 все ще включає її і не має зауважень, що вона відбудеться в будь-який час незабаром.

У Windows стандартним способом є CryptGenRandom () .


2

Я не був задоволений жодною з відповідей поки що, тому я написав нову функцію випадкового поплавця. Це робить побітні припущення щодо типу плаваючих даних. Він все ще потребує функції rand () з принаймні 15 випадковими бітами.

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}

7
цікавий підхід, який я хотів би підкреслити, але я дійсно не розумію, що відбувається
жовтня

2

На мою думку, наведена вище відповідь дає деякий "випадковий" поплавок, але жоден з них не є справді випадковим поплавком (тобто вони пропускають частину представлення поплавця). Перш ніж я поспішаю на свою реалізацію, давайте спочатку подивіться на стандартний формат ANSI / IEEE для плавців:

| знак (1-бітний) | e (8-біт) | f (23-бітний) |

число, представлене цим словом, є (-1 * знак) * 2 ^ e * 1.f

зауважте, що число 'е' є упередженим (з ухилом у 127) числом, таким чином коливаючись від -127 до 126. Найпростіша (і насправді найбільш випадкова) функція - це просто записувати дані випадкового int у поплавок, таким чином

int tmp = rand();
float f = (float)*((float*)&tmp);

зауважте, що якщо ви float f = (float)rand();це зробите, це перетворить ціле число в float (таким чином 10 стане 10.0).

Отже, якщо ви хочете обмежити максимальне значення, ви можете зробити щось на кшталт (не впевнений, чи це працює)

int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f       // note float to int conversion!
tmp %= max_number;
f -= tmp;

але якщо подивитися на структуру поплавця, то можна побачити, що максимальне значення поплавця становить (приблизно) 2 ^ 127, що значно більше, ніж максимальне значення int (2 ^ 32), таким чином виключаючи значну частину числа, які можуть бути представлені поплавком. Це моя остаточна реалізація:

/**
 * Function generates a random float using the upper_bound float to determine 
 * the upper bound for the exponent and for the fractional part.
 * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
 * @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
 * @param sign_flag if sign_flag = 0 the random number is always positive, if 
 *              sign_flag = 1 then the sign bit is random as well
 * @return a random float
 */
float randf(int min_exp, int max_exp, char sign_flag) {
    assert(min_exp <= max_exp);

    int min_exp_mod = min_exp + 126;

    int sign_mod = sign_flag + 1;
    int frac_mod = (1 << 23);

    int s = rand() % sign_mod;  // note x % 1 = 0
    int e = (rand() % max_exp) + min_exp_mod;
    int f = rand() % frac_mod;

    int tmp = (s << 31) | (e << 23) | f;

    float r = (float)*((float*)(&tmp));

    /** uncomment if you want to see the structure of the float. */
//    printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);

    return r;
}

за допомогою цієї функції randf(0, 8, 0)повернеться випадкове число між 0,0 і 255,0


1
у вас помилка. rand ()% frac_mod не працюватиме, оскільки MAX_RAND зазвичай нижче (1 << 23).
ДаніельHsH

Я мушу визнати, що не знаю точного розміру MAX_RAND. Тим не менш, він все одно буде працювати, його, можливо, марне твердження, але воно все одно спрацює. 8% 10 = 8, тож добре, але якщо MAX_RAND завжди менший, то (1 << 23) ви дійсно можете його видалити.
користувач2546926

2
Ні, ти трохи помилився. Як правило, RandMax становить ~ 65 000. Це означає, що з 23 бітів ви робите лише 15 випадкових. Іншим буде, мабуть, нуль. Ви дійсно отримаєте випадкові числа, але з низькою точністю. Наприклад, ваш випадковий генератор може генерувати 0,001 і 0,002, але не може генерувати 0,0017. Таким чином, ви маєте рівномірний розподіл, але низької точності (в 256 разів менше точності, ніж поплавок).
DanielHsH

У цій відповіді є дві помилки. Закріплення діапазону експонентів: int e = (rand() % (max_exp - min_exp)) + min_exp_mod;і мантіса: int f = (int)(frac_mod * (float)rand() / RAND_MAX);заміна відповідних рядків вище. Зауважте, що помилка мантіси є головною: дляRAND_MAX менших 1 << 23ви б лише рандомізували нижчі значущі біти і отримали 0s за найзначніші біти весь час!
BeyelerStudios

2

Якщо ви знаєте, що ваш формат з плаваючою комою - це IEEE 754 (майже всі сучасні процесори, включаючи Intel і ARM), ви можете побудувати випадкове число з плаваючою комою з випадкового цілого числа за допомогою розрядних методів. Це слід враховувати лише в тому випадку, якщо у вас немає доступу до C ++ 11 randomабо Boost.Randomвони набагато кращі.

float rand_float()
{
    // returns a random value in the range [0.0-1.0)

    // start with a bit pattern equating to 1.0
    uint32_t pattern = 0x3f800000;

    // get 23 bits of random integer
    uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());

    // replace the mantissa, resulting in a number [1.0-2.0)
    pattern |= random23;

    // convert from int to float without undefined behavior
    assert(sizeof(float) == sizeof(uint32_t));
    char buffer[sizeof(float)];
    memcpy(buffer, &pattern, sizeof(float));
    float f;
    memcpy(&f, buffer, sizeof(float));

    return f - 1.0;
}

Це дасть кращий розподіл, ніж один, що використовує поділ.


8
Я не впевнений, чому ви говорите, що це дасть "кращий розподіл". Насправді це дасть абсолютно такий самий розподіл, як і справедливий return (float)random23 / (1 << 23). (Так, я щойно перевірив це , модифікувавши вашу функцію random32як параметр і запустивши її для всіх значень від нуля до (1 << 23)-1. І так, ваш метод справді дає абсолютно такі самі результати, як поділ на 1 << 23.)
Ілмарі Каронен

1

Для C ++ він може генерувати реальні числа з плаваючою кількістю в межах, визначених distзмінною

#include <random>  //If it doesnt work then use   #include <tr1/random>
#include <iostream>

using namespace std;

typedef std::tr1::ranlux64_base_01 Myeng; 
typedef std::tr1::normal_distribution<double> Mydist;

int main() { 
       Myeng eng; 
       eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
       Mydist dist(1,10); 

       dist.reset(); // discard any cached values 
       for (int i = 0; i < 10; i++)
       {
           std::cout << "a random value == " << (int)dist(eng) << std::endl; 
       }

       return (0);
}

1
Ви просто скопіювали та вставили код із цієї відповіді? stackoverflow.com/a/1118739/1538531
Дерек

Насправді ні. Я трохи здивований, бачачи, наскільки вони схожі! Але я ініціалізував двигун-генератор січня 1,1970.
Marco167

Досить справедливо. Я помітив, що ти ініціалізував генератор до епохи, але чорт цей код схожий!
Дерек

Мені здається, що дивним є приклад TR1, чи можна пояснити, у яких випадках комусь доведеться використовувати TR1 на відміну від C ++ 11?
Шафік Ягмур

0

rand () повертає int між 0 і RAND_MAX. Щоб отримати випадкове число між 0,0 і 1,0, спочатку киньте int поверненням rand () до float, а потім розділіть на RAND_MAX.


0
#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

Я не міг опублікувати двох відповідей, тож ось друге рішення. log2 випадкові числа, масивні ухили до 0.0f, але це справді випадковий поплавок 1,0f до 0,0f.

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.