It is necessary to generate pseudo-random fractional numbers on the interval (-1; 0) (0; 1).

Googled, thought, found out how to generate them in the gap (0; 1):

double Random(void) { double num = (double)rand() / ((double)rand() + 0.1); return num - floor(ret); } int main() { srand((unsigned)time(NULL)); k = Random(); return 0; } 

Here are the following numbers acceptable for my subtask: enter image description here

But how to generate numbers in the above range, I can not think of ...

  • The fact that the numbers obtained in this way will be distributed unevenly (roughly speaking, the probability of getting 0.5 will be higher than the probability of getting 0.01) - does this require your task? - Yaant
  • My task is the same as it was voiced - you need to get real random numbers on the interval (-1; 0) ∪ (0; 1). In fact, as far as I understand, for my subtask (initialization of the synaptic weights of the neural network) a high degree of randomness is not very important, although desirable. What is important is the specified interval. - kekyc
  • Thank you all for the answers, I will understand. - kekyc
  • one
    Here is a good description, but for C ++: ru.stackoverflow.com/questions/504652/… - Harry

3 answers 3

The simplest self-made version, which works with almost all compilers, except, for some reason, Intel C 15. It is based on the IEEE-754 format. We generate the denominator D as a denormalized number, whose mantissa is 2 32 . The numerator r is generated, which is also denormalized and less than 2 32 (it is not equal to zero). Then divide r by D, guaranteed to get a number between 0 and 1. Then, depending on the sign of s, we make it either positive or negative. Instead of generating s like I can (and even better) use some other number generator from the range from 0 to 2 32 -1 (just NOT rand (), because it has a different range), because this linear generator is not very stable, alternates parity of numbers and repeats through a full cycle.

Unfortunately, the code is machine-dependent, it depends on the order of the bytes in the word and on the IEEE-754 format, therefore it is suitable only for handicraft work, but not for serious projects.

 #include <stdio.h> double r; unsigned int s = 17; static double get_random ( ) { double D = 0.0; do s = 19993*s+1; while (s==0); // s != 0 *((unsigned int*)&D+1) = 1; // D = 0x0000000100000000 r = 0.0; *(unsigned int *)&r = s; // r = 0x00000000[ s ] r /= D; // r < 1.0 if (s&1) r = -r; return r; } int main() { int i; for (i = 0; i<100; i++) printf ("%lf\n", get_random()); return 0; } 
  • An interesting decision .. I thank for the answer! - kekyc

In fact, you have some kind of weird generator. It will be clearly not evenly distributed.

If you do not need a large entropy, you can use

  int t = rand()%65536; t-= 32768; if (t>=0) t++; return t/32768.0; 

If you need something, rand () is in itself a bad idea, especially on the Win platform.

  • Thank you Could you explain / throw off a link where you can figure out which generators are worse, which ones are better, and at least in general, why is my option bad? - kekyc
  • I tried your example, on Windows for 20 runs with a sample of 8 values, not a single positive number was generated .. - kekyc
  • ideone.com/Qj7mXU is strange, within the margin of error. - pavel
  • @kekyc Your option will not say what is bad, but at first glance it seems that it is too complicated yet to generate 2 random numbers, and here is a simple variant ideone.com/U5MSOS on it you can see that values ​​closer to 0 occur more often than 1. In fact In fact, all this needs to be checked with special tests, but the overall picture as a whole is visible. - pavel
  • Stopped on this option. Judging by the sample gives very good results for me. In general, strange things were happening - your code did produce acceptable results on the site, but on my machine I only gave negative values. I dug up my code, but I found nothing interfering with proper operation. Anyway, thanks for the replies; now at least a bit smarter :) - kekyc

You don't have to invent it, you can just google it:

How can I get random integers in a certain range?

The obvious way,

rand() % N /* POOR */

(which tries to return numbers from 0 to N-1) is a poor number. (See question 13.18.) A better method is something like

(int)((double)rand() / ((double)RAND_MAX + 1) * N)

...

For any of these techniques, if necessary; numbers in the range [M, N] could be generated with something like

M + rand() / (RAND_MAX / (N - M + 1) + 1)

And many more tips in the English version of SO:

How to generate a random number from within a range

 unsigned int rand_interval(unsigned int min, unsigned int max) { int r; const unsigned int range = 1 + max - min; const unsigned int buckets = RAND_MAX / range; const unsigned int limit = buckets * range; /* Create equal size buckets all in a row, then fire randomly towards * the buckets until you land in one of them. All buckets are equally * likely. If you land off the end of the line of buckets, try again. */ do { r = rand(); } while (r >= limit); return min + (r / buckets); }