I need to randomly generate bits but the number of bits should be in a definite ratio.
Say I want to generate a 100 bits.
So if the ratio is 3:2
It has to generate 60 0s and 40 1s.
How will I be able to achieve this in C?
Suppose you have want a 1 with probability p where p is double in the inclusive range [0.0,1.0].
Then you can use this logic of rand_bit() below.
#include <stdio.h>
#include <stdlib.h>
int rand_bit(double p){
if(p==1.0){//Unusual but OK exact comparison of double.
return 1;
}
double r=((double)rand())/((double)RAND_MAX);
return r<p?1:0;
}
//Demonstration...
int main(void) {
srand(78721);//Demonstration is reproducible....
const int test=1000000;
int count=0;
double p=0.6;//60% 1s.
for(int i=1;i<=test;++i){
count+=rand_bit(p);
}
double prop=((double)count)/((double)test);
printf("%f (error=%f)\n",prop,(prop-p));
return 0;
}
Typical output:
0.600500 (error=0.000500)
Remember to seed the random number generator with srand(). Pass in a fixed value as above to get a reproducible result or srand((int)time(NULL)); to get different results run-to-run.
Also note that the built in random number generators in C are generally not great.
They're usually fine for games, and OK for generating test cases for business applications but not usually fit for scientific simulations and cryptographically worthless.
The condition if(p==1.0) is there so we can be sure that p==1.0 returns 1 always. p==0.0 is assured by r<p.
Related
I'm building project for studies on ATmega128 with my friend and we have a problem with random number generator (from 0 to 5), because the function always show the same result. We can't add time.h, because AVR Studio didn't accept this.
Code below:
uint8_t randomNumber(uint8_t r){
r = rand()%5;
return r;
}
other try
uint8_t randomNumber(uint8_t min, uint8_t max){
uint8_t = result;
result = min + rand() % (max+1 - min);
return result;
}
Any ideas?
Thanks,
Sebastian
Wow this question sent me down the rabbit hole.
Pseudorandom numbers are relatively easy to generate.
Truly random numbers are VERY hard to generate.
The quality of your random number (whether biases appear in it) depends completely on your seed value.
Seed values for random number generators must be (wait for it) random, otherwise people can guess which numbers you are using, defeating the randomness of your generator.
Where to get a random seed value from?
Options proposed by the internet:
Natural noise from the environment (read an adc, or... https://www.fourmilab.ch/hotbits/ (i know it's not practical for an arduino project, but interesting none the less)).
Time user inputs (humans are by default not precise).
Timing differences between crystals. [https://en.wikipedia.org/wiki/Clock_drift]
Mild disclaimer:
1/3 have been proven unsafe in commercial environments, and it's easy to see how #2 could be gamed by using a computer instead of a human.
So the quickest way is probably to use a floating ADC. Before you think this is a good idea: https://skemman.is/bitstream/1946/10689/1/ardrand.pdf
Remember: Larger pools of seeds increases the randomness (aka using a 32bit random seed value is better than using a boolean random seed value).
ADC's on the 128 have 1024 values, realistically, a floating point value will trend to far less than that (I've read you should treat it like 32).
To improve your chances of getting random numbers, take the lowest bit from the adc reading multiple times (aka read the adc 16 times to get a 16 bit "random" number).
Assuming you have your adc set up etc.
UNTESTED PSEUDO CODE
/* srand example */
#include <stdio.h> /* printf, NULL */
#include <stdlib.h> /* srand, rand */
#include <avr/io.h>
//pseudo code. you must implement init_adc() and read_adc()
int main ()
{
//Init and seed.
uint16_t u_rand_val = 0;
uint16_t u_seed_rand_val = 0;
init_adc();
//Note we're assuming the channel that you are reading from is FLOATING or hooked up to something very noisy.
//Gather bits from the adc, pushing them into your pseudorandom seed.
for(uint8_t i=0; i<16; i++){
u_seed_rand_val = u_seed_rand_val<<1 | (read_adc()&0b1);
}
srand (u_seed_rand_val);
while(1){
//Do whatever you were going to do.
//Note that calls to rand() use the seed set up by srand above.
u_rand_val = rand()%5;
print("Cur val:%u", u_rand_val);
}
return 0;
}
For example, we can use internal rand(), but it is the worst choice:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
float randoms(float min, float max)
{
return (float)(rand())/RAND_MAX*(max - min) + min;
}
int main()
{
srand((unsigned int)time(0));
printf("%f\n",randoms(-100.001, 100.001));
return 0;
}
I've searched, but not found any working example of PCG library for float numbers.
In the answer I would like to share my own experience of using PCG random library to generate float numbers within a fixed range. Previously I've used arc4random library for this goal, but PCG is simpler and has no complicated dependencies.
How to generate float numbers set within a range(?)
Using various random functions can improve the random properties of integers generated. The application of those integers to make a float has other pitfalls not address by OP regardless of the random function. Also see #Serge Ballesta.
The simplistic use of the following risks generating a value outside the range [min...max]
float retval = (float)some_rand()/SOME_RAND_MAX*(max - min) + min;
The 2 conversion of the 2 integers to float incur rounding. float /,*,-,* each can contribute 4 more roundings. Given that min/max may come in many valid combinations, it is prudent to guard against an out-of-range retval
float retval;
assert(min < max); // may want to assert min/max are finite too
do {
retval = 1.0f*some_rand()/SOME_RAND_MAX*(max - min) + min;
} while (!(retval >= min && retval <= max));
return retval;
Note that the setting of FLT_EVAL_METHOD complicates any assessment as some calculations may be conducted as double/long double.
Potential losses of desired random properties:
The use of pcg32_random_r() versus rand() does provide numbers with more attractive integer random properties, yet those improved attributes are reduced with casual floating-point code.
(Assume binary32 for float)
Consider how the following can uniformly generate values in the range [0...224] yet values larger than that, it will be only even numbers. It becomes spottier with larger numbers up to (float)UINT32_MAX. This would be acceptable for another function that was now to return that value, but the scaling of *(max - min) + min redistributes those values in a way that can become very non-uniform.
(float)pcg32_random_r(...);
A simple way to address some of these short comings is to use higher precision like double math within float randoms(float min, float max), yet that approach does not help with long double randomsL(long double min, long double max)
You PCG will generate some number of random bits. Let's say that's 32. A double precision float has 53 bits of significand, so you'll need more than one call. So, call the function twice, and pack the two calls into a 64-bit integer:
int64_t x = (pcg32() << 32) | pcg32();
Then divide that integer down to the desired range (this is the signed -100...100 version):
double r = ((double)x * 100.0) / 9223372036854775808.0; // 2**63
// main.c
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
// PCH library headers
#include "pcg_variants.h"
#include "entropy.h" // Wrapper around /dev/random
int main(int argc, char** argv)
{
pcg32_random_t rng;
// Seed with external entropy
uint64_t seeds[2];
entropy_getbytes((void*)seeds, sizeof(seeds));
pcg32_srandom_r(&rng, seeds[0], seeds[1]);
for (int i = 0; i < 10; ++i)
{
uint32_t random_unsigned_integer = pcg32_random_r(&rng);
float max = 100.001;
float min = -100.001;
float q = (float)(random_unsigned_integer)/((float)UINT32_MAX)*(max - min) + min;
// Shows 10 float numbers in specified range.
printf("%.6f\n", q);
}
return 0;
}
Compile:
gcc -std=c11 -o pcg_float main.c
This is the code which I have written to find approx square root a non perfect number(in the order 0.0001 and also exact square root of a perfect square. It is working with non perfect square numbers but not perfect. When I put 25 it gives 5.000068
#include<stdio.h>
int main()
{
float a,i,count;
scanf("%f",&a);
for(count=1;(1);count=count+0.0001)
{
i=count*count;
if (i<=a)
break;
}
printf("%f",count);
return 0;
}
Your method is wrong for computing square roots.
You deserve a bad grade for not reading a bit about square roots. Understanding the problem is the first step for any software development.
First, you should read The Floating Point Guide and the classical What Every Programmer Should Know About Floating-Point Arithmetic. It explains why your program cannot work (i.e. gives inaccurate results).
Then, your program is very inefficient (for large input numbers like several billions, it takes an enormous amount of computing time; for very small numbers like 0.01 it probably never terminates). Learn about Newton-Raphson's method, perhaps by reading some basic math book.
Notice that many fixpoint computations translate to iterative algorithms.
There are two things that are faulty with your code:
Floating point is not exact. If you want more accuracy, use double, not float.
Your increment value is too large. If you incremented by a smaller amount you would (or should) get the desired value: See here: http://ideone.com/7XM2IK
The next issue doesn't affect your code now, but be warned anyway:
Do not use floating point arithmetic as a loop counter. To fix this issue, normalize your loop to do integer counts, and do the floating point inside the loop:
int count;
float dCount = 1.0;
float i, a;
//...
for (count=0; count < 100000; ++count)
{
//...
}
See this link: https://www.securecoding.cert.org/confluence/display/java/NUM09-J.+Do+not+use+floating-point+variables+as+loop+counters
If you dont want to struggle with books and math:
#include <stdio.h>
#include <math.h>
int main()
{
float n = 25;// ofc use scanf xD
n=sqrt(n);
printf("%.5f", n);
return 0;
}
I've written a C function that I think selects integers from a uniform distribution with range [rangeLow, rangeHigh], inclusive. This isn't homework--I'm just using this in some embedded systems tinkering that I'm doing for fun.
In my test cases, this code appears to produce an appropriate distribution. I'm not feeling fully confident that the implementation is correct, though.
Could someone do a sanity check and let me know if I've done anything wrong here?
//uniform_distribution returns an INTEGER in [rangeLow, rangeHigh], inclusive.
int uniform_distribution(int rangeLow, int rangeHigh)
{
int myRand = (int)rand();
int range = rangeHigh - rangeLow + 1; //+1 makes it [rangeLow, rangeHigh], inclusive.
int myRand_scaled = (myRand % range) + rangeLow;
return myRand_scaled;
}
//note: make sure rand() was already initialized using srand()
P.S. I searched for other questions like this. However, it was hard to filter out the small subset of questions that discuss random integers instead of random floating-point numbers.
Let's assume that rand() generates a uniformly-distributed value I in the range [0..RAND_MAX],
and you want to generate a uniformly-distributed value O in the range [L,H].
Suppose I in is the range [0..32767] and O is in the range [0..2].
According to your suggested method, O= I%3. Note that in the given range, there are 10923 numbers for which I%3=0, 10923 number for which I%3=1, but only 10922 number for which I%3=2. Hence your method will not map a value from I into O uniformly.
As another example, suppose O is in the range [0..32766].
According to your suggested method, O=I%32767. Now you'll get O=0 for both I=0 and I=32767. Hence 0 is twice as likely than any other value - your method is again nonuniform.
The suggest way to generate a uniform mapping is as follow:
Calculate the number of bits that are needed to store a random value in the range [L,H]:
unsigned int nRange = (unsigned int)H - (unsigned int)L + 1;
unsigned int nRangeBits= (unsigned int)ceil(log((double(nRange) / log(2.));
Generate nRangeBits random bits
this can be easily implemented by shifting-right the result of rand()
Ensure that the generated number is not greater than H-L.
If it is - repeat step 2.
Now you can map the generated number into O just by adding a L.
On some implementations, rand() did not provide good randomness on its lower order bits, so the modulus operator would not provide very random results. If you find that to be the case, you could try this instead:
int uniform_distribution(int rangeLow, int rangeHigh) {
double myRand = rand()/(1.0 + RAND_MAX);
int range = rangeHigh - rangeLow + 1;
int myRand_scaled = (myRand * range) + rangeLow;
return myRand_scaled;
}
Using rand() this way will produce a bias as noted by Lior. But, the technique is fine if you can find a uniform number generator to calculate myRand. One possible candidate would be drand48(). This will greatly reduce the amount of bias to something that would be very difficult to detect.
However, if you need something cryptographically secure, you should use an algorithm outlined in Lior's answer, assuming your rand() is itself cryptographically secure (the default one is probably not, so you would need to find one). Below is a simplified implementation of what Lior described. Instead of counting bits, we assume the range falls within RAND_MAX, and compute a suitable multiple. Worst case, the algorithm ends up calling the random number generator twice on average per request for a number in the range.
int uniform_distribution_secure(int rangeLow, int rangeHigh) {
int range = rangeHigh - rangeLow + 1;
int secureMax = RAND_MAX - RAND_MAX % range;
int x;
do x = secure_rand(); while (x >= secureMax);
return rangeLow + x % range;
}
I think it is known that rand() is not very good. It just depends on how good of "random" data you need.
http://www.azillionmonkeys.com/qed/random.html
http://www.linuxquestions.org/questions/programming-9/generating-random-numbers-in-c-378358/
http://forums.indiegamer.com/showthread.php?9460-Using-C-rand%28%29-isn-t-as-bad-as-previously-thought
I suppose you could write a test then calculate the chi-squared value to see how good your uniform generator is:
http://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test
Depending on your use (don't use this for your online poker shuffler), you might consider a LFSR
http://en.wikipedia.org/wiki/Linear_feedback_shift_register
It may be faster, if you just want some psuedo-random output. Also, supposedly they can be uniform, although I haven't studied the math enough to back up that claim.
A version which corrects the distribution errors (noted by Lior),
involves the high-bits returned by rand() and
only uses integer math (if that's desirable):
int uniform_distribution(int rangeLow, int rangeHigh)
{
int range = rangeHigh - rangeLow + 1; //+1 makes it [rangeLow, rangeHigh], inclusive.
int copies=RAND_MAX/range; // we can fit n-copies of [0...range-1] into RAND_MAX
// Use rejection sampling to avoid distribution errors
int limit=range*copies;
int myRand=-1;
while( myRand<0 || myRand>=limit){
myRand=rand();
}
return myRand/copies+rangeLow; // note that this involves the high-bits
}
//note: make sure rand() was already initialized using srand()
This should work well provided that range is much smaller than RAND_MAX, otherwise
you'll be back to the problem that rand() isn't a good random number generator in terms of its low-bits.
I'd like to find an unskewed way of getting random numbers in C (although at most I'm going to be using it for values of 0-20, and more likely only 0-8). I've seen this formula but after running some tests I'm not sure if it's skewed or not. Any help?
Here is the full function used:
int randNum()
{
return 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
}
I seeded it using:
unsigned int iseed = (unsigned int)time(NULL);
srand (iseed);
The one suggested below refuses to work for me I tried
int greek;
for (j=0; j<50000; j++)
{
greek =rand_lim(5);
printf("%d, " greek);
greek =(int) (NUM * (rand() / (RAND_MAX + 1.0)));
int togo=number[greek];
number[greek]=togo+1;
}
and it stops working and gives me the same number 50000 times when I comment out printf.
Yes, it's skewed, unless your RAND_MAX happens to be a multiple of 10.
If you take the numbers from 0 to RAND_MAX, and try to divide them into 10 piles, you really have only three possibilities:
RAND_MAX is a multiple of 10, and the piles come out even.
RAND_MAX is not a multiple of 10, and the piles come out uneven.
You split it into uneven groups to start with, but throw away all the "extras" that would make it uneven.
You rarely have control over RAND_MAX, and it's often a prime number anyway. That really only leaves 2 and 3 as possibilities.
The third option looks roughly like this:
[Edit: After some thought, I've revised this to produce numbers in the range 0...(limit-1), to fit with the way most things in C and C++ work. This also simplifies the code (a tiny bit).
int rand_lim(int limit) {
/* return a random number in the range [0..limit)
*/
int divisor = RAND_MAX/limit;
int retval;
do {
retval = rand() / divisor;
} while (retval == limit);
return retval;
}
For anybody who questions whether this method might leave some skew, I also wrote a rather different version, purely for testing. This one uses a decidedly non-random generator with a very limited range, so we can simply iterate through every number in the range. It looks like this:
#include <stdlib.h>
#include <stdio.h>
#define MAX 1009
int next_val() {
// just return consecutive numbers
static int v=0;
return v++;
}
int lim(int limit) {
int divisor = MAX/limit;
int retval;
do {
retval = next_val() / divisor;
} while (retval == limit);
return retval;
}
#define LIMIT 10
int main() {
// we'll allocate extra space at the end of the array:
int buckets[LIMIT+2] = {0};
int i;
for (i=0; i<MAX; i++)
++buckets[lim(LIMIT)];
// and print one beyond what *should* be generated
for (i=0; i<LIMIT+1; i++)
printf("%2d: %d\n", i, buckets[i]);
}
So, we're starting with numbers from 0 to 1009 (1009 is prime, so it won't be an exact multiple of any range we choose). So, we're starting with 1009 numbers, and splitting it into 10 buckets. That should give 100 in each bucket, and the 9 leftovers (so to speak) get "eaten" by the do/while loop. As it's written right now, it allocates and prints out an extra bucket. When I run it, I get exactly 100 in each of buckets 0..9, and 0 in bucket 10. If I comment out the do/while loop, I see 100 in each of 0..9, and 9 in bucket 10.
Just to be sure, I've re-run the test with various other numbers for both the range produced (mostly used prime numbers), and the number of buckets. So far, I haven't been able to get it to produce skewed results for any range (as long as the do/while loop is enabled, of course).
One other detail: there is a reason I used division instead of remainder in this algorithm. With a good (or even decent) implementation of rand() it's irrelevant, but when you clamp numbers to a range using division, you keep the upper bits of the input. When you do it with remainder, you keep the lower bits of the input. As it happens, with a typical linear congruential pseudo-random number generator, the lower bits tend to be less random than the upper bits. A reasonable implementation will throw out a number of the least significant bits already, rendering this irrelevant. On the other hand, there are some pretty poor implementations of rand around, and with most of them, you end up with better quality of output by using division rather than remainder.
I should also point out that there are generators that do roughly the opposite -- the lower bits are more random than the upper bits. At least in my experience, these are quite uncommon. That with which the upper bits are more random are considerably more common.