Перемешивание массива [РЕШЕНО]

Автор raptor, 8 февраля 2011, 22:13

0 Пользователи и 1 гость просматривают эту тему.

mathnew

#30
Для желающих поиграться с rand() в Linux и Windows программа, записывающая в файл случайные числа:
/*            rand64k38.c             */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

main() {
 FILE *fm;
 char str[12];
 long unsigned offset,size;

 printf("\n\nname of file for output : ");
 gets(str);

 printf("number = ");
 scanf("%ld",&size);

 srand(time(NULL));

 fm=fopen(str,"ab");
 for(offset=0; offset < size; offset++)
 {
   fprintf(fm,"%f", (float) (rand()/65536)/32768);
   fprintf(fm,"%c%c",toascii(13),toascii(10));
 }
 fclose(fm);
}



Можно менять 65536 и 32768 (на 32767) и смотреть что получится.

bormant

Цитата: Клио от 12 февраля 2011, 15:35
Цитата: Клио от 12 февраля 2011, 11:56+        nRand = ( nRand / (double)(RAND_MAX + 1) );
Совсем ку-ку.После этого патча все rnd стали почему-то отрицательными.
Это "почему-то" называется стандарт языка C или языка C++.

По шагам:
1) RAND_MAX это #define RAND_MAX 32767
2) define-ы раскрываются до передачи исходника компилятору, компилятор видит
nRand = ( nRand / (double)(32767 + 1) );
3) для представления константы 32767 достаточно short int, для представления 1 достаточно short int
4) вычисляется (short int)32767 + (short int)1 -- 0x7FFF+0x0001 = 0x8000 = -32768 (да, переполнение)
5) double(-32768)=-32768.0
6) генерируется код для вычисления во время исполнения:
nRand = nRand / -32768.0
7) поскольку nRand при предыдущем вычислении принимает значения [0;32767], т.е. только положительные, то
после nRand = nRand / -32768.0  nRand отрицательно.
Автору на яд. Поддержать форум.

bormant

mathnew,
Если я правильно путаю, будучи скомпилированной под Windows в MS VC, она будет возвращать "случайные" нули...
Ибо по документации MS VC RAND_MAX равен 32767, соответственно, даже для самого большого значения rand(): 32767/65536 равно 0, (float)(32767/65536)/32768 тоже равно 0.

У кого есть MS VC под руками, проверьте.
Автору на яд. Поддержать форум.

mathnew

#33
Совершенно верно. Поэтому я и написал
ЦитироватьМожно менять 65536 и 32768 (на 32767) и смотреть что получится.
Для Windows (и DOS) нужно заменить 65536 на 1.

Вообще-то, RAND_MAX определяется использованным компилятором (и определением функции rand() в его библиотеке функций).
Т.е., теоретически RAND_MAX может быть одинаковым и для Linux и для Windows.

mathnew

Кстати, в MS Visual Studio есть и другие функции для генерации псевдослучайных чисел:
RtlGenRandom
CryptGenRandom
...

bormant

mathnew,
указанные функции есть не в MS Visual Studio, а в MS Windows, не путайте.
Автору на яд. Поддержать форум.

mathnew

Ну ладно, если уж совсем точно, то в Windows API.
А компилятор Visual Studio вовсю использует API.
Цитировать...the Microsoft C++ library function rand_s uses RtlGenRandom and is recommended by Microsoft for secure applications...

Рыбка Рио

Цитата: bormant от 13 февраля 2011, 15:20
Это "почему-то" называется стандарт языка C или языка C++.
Спасибо, bormant.

Кстати, почему (rand()/65536)/32768 , а не (rand()/65536) % 32768 - это остаток от деления должен быть кажется, потому и не превышает 32767.
ubuntu 12.04 + LibO3.6.0

Рыбка Рио

Можно ещё вот такой макрос запустить.
Sub TestRnd
tries& = 1000000
s% = 0
Dim dbll As Double
Dim dbll2 As Double

For i& = 1 To tries
dbll2 = Rnd
If dbll2 > dbll Then dbll=dbll2
Next
MsgBox dbll
End Sub


На линуксе гранулы меньше, чем 1/32768.
ubuntu 12.04 + LibO3.6.0