Автор Гілка: Генератор випадкових величин.  (Прочитано 4069 раз)

Відсутній Сергій Лисовенко

  • Літератор
  • ******
  • дописів: 1489
  • Карма: +0/-0
Потрібні випадкові величини подвійної точності, що коливаються в межах -1 1
Класичний  long int random(void); трішечки не годиться: точність в нього велика лише на 64 розрядній системі.
на  основі даних з вікіпедії написав свого
double randd(FILE * urandom)
{
  double d;
  int *i = (void *)&d + sizeof (double) - sizeof (int);

  fread(&d, 1, sizeof (d), urandom);
  *i &= 0x800fffff;
  *i |= 0x3fe00000;
  return d;
}
Знаю, що велосипед ще той, але ж їздить просто цікаво, чи не може виникнути така дурна ситуація, що мій рандом вискочить з діапазону? Ну і якщо в когось є кращі варіанти - пропонуйте.
P.S.
Рандом зі свинкою: хай віндузятник спробує з ним скомпілити програму  ;D
Якщо Лінукс написали студенти - нехай вони під ним і навчаються.

Відсутній noddeat

  • Кореспондент
  • ***
  • дописів: 197
  • Карма: +0/-0
Filenames are infinite in length, where infinity is set to to 255 characters. Peter Collinson, "The Unix File System"

Відсутній noddeat

  • Кореспондент
  • ***
  • дописів: 197
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #2 : 2009-04-03 13:18:26 »
Цитата
Класичний  long int random(void); трішечки не годиться: точність в нього велика лише на 64 розрядній системі.
щось не розумію: а якщо згенерувати в long int від -10^16 до +10^16, а потім поділити на 10^16 ? чи діапазон long int вужчий (ліньки гуглити)?
Filenames are infinite in length, where infinity is set to to 255 characters. Peter Collinson, "The Unix File System"

Відсутній Сергій Лисовенко

  • Літератор
  • ******
  • дописів: 1489
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #3 : 2009-04-03 13:43:15 »
Що там його гуглити?
Гуглим прямо на вінчестері:
grep INT_MAX /usr/include/limits.h
#  define INT_MIN       (-INT_MAX - 1)
#  define INT_MAX       2147483647
#  define UINT_MAX      4294967295U
А той же алгоритим генрування випадкових чисел, що використовує glibc не сильно радує, бо точки сідають на дискретні місця. Втім, не знаю наскільки якісний алгоритм генерації псевдовипадкових чисел в ядра Linux, але там хоч трішки "живої" ентропії є.
Якщо Лінукс написали студенти - нехай вони під ним і навчаються.

Відсутній noddeat

  • Кореспондент
  • ***
  • дописів: 197
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #4 : 2009-04-03 15:45:52 »
якщо не таємниця: яку задачу ви вирішуєте?
Filenames are infinite in length, where infinity is set to to 255 characters. Peter Collinson, "The Unix File System"

Відсутній Сергій Лисовенко

  • Літератор
  • ******
  • дописів: 1489
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #5 : 2009-04-03 18:59:08 »
Звичайно, не таємниця: засипаю в тривимірний куб точки.
Якщо Лінукс написали студенти - нехай вони під ним і навчаються.

Відсутній noddeat

  • Кореспондент
  • ***
  • дописів: 197
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #6 : 2009-04-03 20:47:02 »
мені здається, з нею стандартний rand справляється. хоча певно ви праві, що /dev/random є більш випадковим, ніж з glibc.
Filenames are infinite in length, where infinity is set to to 255 characters. Peter Collinson, "The Unix File System"

Відсутній Сергій Лисовенко

  • Літератор
  • ******
  • дописів: 1489
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #7 : 2009-04-03 21:04:46 »
Тупий рандом накидує точки в дискретні місця: вони на лінії стають. А от в urandom купа мотлоху летить :)
P.S.
Нось я прорахувався: в 64-розрядній системі int=4; long int=8; void* =8; double=8; тобто для неї все актуальне, що і для 32 - розрядної (збільшені лише пойнтери та довгі цілі, але про них ми не говорим).
« Змінено: 2009-04-03 21:22:35 від serg_ik »
Якщо Лінукс написали студенти - нехай вони під ним і навчаються.

Відсутній Сергій Лисовенко

  • Літератор
  • ******
  • дописів: 1489
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #8 : 2009-04-06 13:41:42 »
Емпірично нарив в генераторі дюру, згодом вчитування в вікі-сторінку про плаваючу кому показало, що то - супердірка. Тож код виправив.
double oqut_random(FILE * urandom)
{
  double d;
  int *i = (void *)&d + sizeof (double) - sizeof (int);

  fread(&d, 1, sizeof (d), urandom);
  *i &= 0x800fffff;
  *i |= 0x3ff00000;
  return (d > 0.) ? d - 1. : d + 1.;
}
« Змінено: 2009-04-06 13:54:04 від serg_ik »
Якщо Лінукс написали студенти - нехай вони під ним і навчаються.

Відсутній RomadinR

  • Кореспондент
  • ***
  • дописів: 123
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #9 : 2009-04-06 14:17:55 »
Взагалі, перш ніж вибрати генератор (псевдо)випадкових чисел, потрібно визначитися з деякими вимогами до розподілу цих чисел. Це дуже залежить від того, для чого ви їх будете використовувати. Для методів Монте-Карло найкраще підходять генератори із рівномірним розподілом, хоч бувають випадки (особливо при дослідженні негладких функцій), коли краще (з точки зору економії машинного часу) використати нерівномірний розподіл із максимумом у потрібних областях (легко отримується із рівномірного відповідними перетвореннями).
Одним із найшвидших генераторів псевдовипадкових чисел, які мають рівномірний розподіл і досить великий період повторення  послідовності(~2^90, якщо не помиляюся) є алгоритм xorshift.

Відсутній Сергій Лисовенко

  • Літератор
  • ******
  • дописів: 1489
  • Карма: +0/-0
Re: Генератор випадкових величин.
« Відповідей #10 : 2009-04-06 16:31:46 »
Одним із найшвидших генераторів псевдовипадкових чисел, які мають рівномірний розподіл і досить великий період повторення  послідовності(~2^90, якщо не помиляюся) є алгоритм xorshift.
unsigned long xorshiftrand(void) {
  static unsigned long
    x=123456789, y=362436069,
    z=521288629, w=88675123;
  unsigned long t;
  t = x ^ (x << 11);
  x = y; y = z; z = w;
  return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}
Алгоритм і справді --- торпеда :)

Якщо підійти формально --- той код, який я обізвав "генератором" насправді ним не є, то --- лише обгортка до ядрового генератора псевдовипадкових байтів, залишається лише сподіватись, що в ядрі досить пристойний алгоритм генерації ПВЧ плюс генерація випадкових чисел користувачем.
Властивість обгортки: створює випадкові числа з рівномірним розподілом: -1<x<1 при умові рівномірності розподілу псевдовипадкових байтів. Закидання кубика точками і розрахунок з цього діла парної кореляційної функції дало кривульку, що досить тісно прилягала до одинички :) (за виключенням точок на початку  --- там вічно якийсь дурдом коїться ;) )
« Змінено: 2009-04-06 16:33:03 від serg_ik »
Якщо Лінукс написали студенти - нехай вони під ним і навчаються.