beldmit: (Default)
[personal profile] beldmit
Последними дискуссиями у Витуса навеяло.

Я очень хорошо помню этот момент. Год был 1992-й, я только поступил в институт. Мы с Лешей Студеновым собирались писать на Pascal-е (C я тогда не знал) некую экономическую игру. Договорились вечером, разошлись по домам, и я задумался.

Игра начиналась с раздачи карт. Карты естественным образом ложились в двумерный массив, а раздавать надо было датчиком случайных чисел. И тут я задумался - а что, если одна и та же карта выпадет в раздаче дважды? Немного подумав, я понял, что просто повторять раздачу этой карты бесполезно - то же число может выпасть и третий раз. Мне стало очень грустно. И тут меня осенило - есть же цикл while! Он решит все проблемы!

Второго такого озарения с тех пор в моем програмистском опыте не было. Но ощущения я запомнил навсегда.

Date: 2009-03-02 09:05 pm (UTC)
From: [identity profile] beldmit.livejournal.com
Ну так на то они и случайные...

Кто-то тут недавно рассказывал про GPF, вызванный ошибкой в самописном рандоме - возвращал число не от 0 до n-1, а до n - а результат использовался как индекс в массиве.

Date: 2009-03-02 09:14 pm (UTC)
From: [identity profile] slobin.livejournal.com
Вот у него ровно это и было! Но он подробно тестирует свой продукт в системах с RAND_MAX = 2**31-1, а в системах с RAND_MAX = 2**15-1 так, лишь бы было. Хотя пользователей у него в этих системах дохрена. А randomize (перемешать массив) вызывает rand по числу элементов массива -- у меня около 750-и. Вот один раз из сорока оно и падало. Ну и другая аналогичная ошибка у него была в том же коде, я просто стал просматривать окрестности и заметил.

ПыСы: генератор совершенно не обязан быть самописным. Просто сишники с молоком матери впитали, что верхняя граница диапазона всегда исключительная (i=0;i<n;i++), а rand определена в stdlib как возвращающая величины от 0 до RAND_MAX включительно. Плакать после слова "грабли".

... Зачем ты выключил свопинг? ...

Date: 2009-03-02 09:30 pm (UTC)
From: [identity profile] beldmit.livejournal.com
Маны надо читать. Внимательно.

Date: 2009-03-02 09:37 pm (UTC)
From: [identity profile] slobin.livejournal.com
Само собой. Но согласись, что, когда весь язык пропитан духом "верхняя граница -- это следующий после", то в одном месте в стандартной библиотеке сделать её включительной -- изящный ход. Причём мне в каком-то смысле повезло, что в mingw такой куцый интервал -- у меня ошибка стала довольно быстро вылезать в реальном коде (тот самый один из сорока).

... Вы сбиваете с толку весь Париж! ...

Date: 2009-03-03 05:12 am (UTC)
From: [identity profile] beldmit.livejournal.com
Ты знаешь, я как правило не помню порядок аргументов и тому подобные вещи.

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

Из ISO 9899:1999 (E)

Date: 2009-03-03 07:43 am (UTC)
yurikhan: (Default)
From: [personal profile] yurikhan

7.20.2.1/2: The rand function computes a sequence of pseudo-random integers in the range 0 to RAND_MAX.

[…]

7.20.2.2/5: Example: The following functions define a portable implementation of rand and srand.

static unsigned long int next = 1;

int rand(void) // RAND_MAX assumed to be 32767
{
    next = next * 1103515245 + 12345;
    return (unsigned int)(next / 65536) % 32768;
}

void srand(unsigned int seed)
{
    next = seed;
}

То есть да, формулировка недостаточно точная, но пример всё проясняет.

Profile

beldmit: (Default)
Dmitry Belyavskiy

December 2025

S M T W T F S
 123456
78910111213
14151617181920
2122 2324252627
28 29 3031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 10th, 2026 02:51 pm
Powered by Dreamwidth Studios