Generating a random 32 bit hexadecimal value in C - c

What would be the best way to generate a random 32-bit hexadecimal value in C? In my current implementation I am generating each bit separately but the output is not completely random ... many values are repeated several times. Is it better to generate the entire random number instead of generating each bit separately?
The random number should make use of the entire 32 bit address space (0x00000000 to 0xffffffff)
file = fopen(tracefile,"wb"); // create file
for(numberofAddress = 0; numberofAddress<10000; numberofAddress++){ //create 10000 address
if(numberofAddress!=0)
fprintf(file,"\n"); //start a new line, but not on the first one
fprintf(file, "0 ");
int space;
for(space = 0; space<8; space++){ //remove any 0 from the left
hexa_address = rand() % 16;
if(hexa_address != 0){
fprintf(file,"%x", hexa_address);
space++;
break;
}
else if(hexa_address == 0 && space == 7){ //in condition of 00000000
fprintf(file,"%x", "0");
space++;
}
}
for(space; space<8; space++){ //continue generating the remaining address
hexa_address = rand() % 16;
fprintf(file,"%x", hexa_address);
}
}

x = rand() & 0xff;
x |= (rand() & 0xff) << 8;
x |= (rand() & 0xff) << 16;
x |= (rand() & 0xff) << 24;
return x;
rand() doesn't return a full random 32-bit integer. Last time I checked it returned between 0 and 2^15. (I think it's implementation dependent.) So you'll have to call it multiple times and mask it.

Do this way.It creates a bigger number than the earlier logic .If you are interested the MSB then the below logic is good .:
/** x = rand() ^ rand()<<1; **/
#include <algorithm>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <string>
#include <stdio.h>
int main () {
int i, n;
n = 50;
uint x,y ;
//4294967295 :UNIT_MAX
/* Intializes random number generator */
srand((unsigned) time(0));
for( i = 0 ; i < n ; i++ ) {
/**WAY 1 **/
x = rand() ^ rand()<<1;
printf("x:%u\t",x);
printf("Difference1:(4294967295 - %u) = %u\n",x,(4294967295 - x));
/**WAY 2 **/
y = rand() & 0xff;
y |= (rand() & 0xff) << 8;
y |= (rand() & 0xff) << 16;
y |= (rand() & 0xff) << 24;
printf("y:%u\t",y);
printf("Difference2:(4294967295 - %u) = %u\n",y,(4294967295 - y));
printf("Difference between two is = %u\n",(x) - (y));
}
printf("End\n");
return(0);
}

You can just create any random number that's at least 32 bit wide and format that as hex. Examples:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
uint32_t n;
n = mrand48(); // #1
n = rand(); // #2
FILE * f = fopen("/dev/urandom", "rb");
fread(&n, sizeof(uint32_t), 1, f); // #3
// ... etc. etc. E.g. Windows Crypto API
char hex[9];
sprintf(hex, "%08X", n);
Now hex is a string containing eight random hexadecimal digits. Don't forget to seed the various pseudo random number generators (using srand48() and srand(), respectively, for #1 and #2). Since you'll essentially have to seed the PRNGs from random source with at least one 32-bit integer, you might as well tap the random source directly (unless you're using time() or something "non-random" like that).

Related

Why is the wrong binary number displayed?

Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int x;
x = 1000000;
printf("%ld\n", x);
for(int i = 0; i < 32; i++)
{
printf("%c", (x & 0x80) ? '1' : '0');
x <<= 1;
}
printf("\n");
return 0;
}
This code is supposed to convert a decimal int to binary, but why doesn't it work correctly?
P.S. I solved this problem by replacing 0x80 with 0x80000000. But why was the wrong number displayed at 0x80?
EDIT2:
OP asks "P.S. I solved this problem by replacing 0x80 with 0x80000000. But why was the wrong number displayed at 0x80?"
What was wrong was 0x80 is equal to 0x00000080. 0x80 will never test any bits above b7 (where bits, right to left, are numbered b0 to b31.
The corrected value, 0x80000000, sets the MSB high and can be used (kind of) to 'sample' each bit of the data as the data value is 'scrolled' to the left.
//end edit2
Two concerns:
1) Mucking with the sign bit of a signed integer can be problematic
2) "Knowing" there are 32 bits can be problematic.
The following makes fewer presumptions. It creates a bit mask (only the MSB is set in an unsigned int value) and shifts that mask toward the LSB.
int main() {
long int x = 100000;
printf("%ld\n", x);
for( unsigned long int bit = ~(~0u >> 1); bit; bit >>= 1 )
printf("%c", (x & bit) ? '1' : '0');
printf("\n");
return 0;
}
100000
00000000000000011000011010100000
Bonus: Here is a version of the print statement that doesn't involve branching:
printf( "%c", '0' + !!(x & bit) );
EDIT:
Having seen the answer by #Lundin, the suggestion to insert SP's to improve readability is an excellent idea! (Full credit to #Lundin.)
Below, not only is the long string of bits output divided into "hexadecimal" chunks, but the compile time value is shown in a way to easily see it is 10million. (1e7 would have done, too.)
A new-and-improved version:
#include <stdio.h>
#include <stdlib.h>
int main() {
long int x = 10 * 1000 *1000;
printf("%ld\n", x);
for( unsigned long int bit = ~(~0u >> 1); bit; bit >>= 1 ) {
putchar( '0' + !!(x & bit) );
if( bit & 0x11111111 ) putchar( ' ' );
}
putchar( '\n' );
return 0;
}
10000000
0000 0000 1001 1000 1001 0110 1000 0000
1000000 dec = 11110100001001000000 bin.
80 hex = 10000000 bin.
And this doesn't make much sense at all:
11110100001001000000
& 10000000
Instead fix the loop body to something like this:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
long int x;
x = 1000000;
printf("%ld\n", x);
for(int i = 0; i < 32; i++)
{
unsigned long mask = 1u << (31-i);
printf("%c", (x & mask) ? '1' : '0');
if((i+1) % 8 == 0) // to print a space after 8 digits
printf(" ");
}
printf("\n");
return 0;
}
Without using an integer counter to see what digit is at the ith position, you can instead use an unsigned variable which is equal to 2^i at the ith iteration. If this variable is unsigned, when it overflows it will become zero. Here is how the code would look like. It displays the number in reversed order (first position means the coefficient of 2^0 in the polynomial decomposition of the number).
int
main()
{
int x;
x = 1000000;
printf("%lx\n", x);
for(unsigned b = 1; b; b<<=1)
printf("%c", x & b ? '1':'0');
printf("\n");
return 0;
}
I would use functions
void printBin(long int x)
{
unsigned long mask = 1UL << (sizeof(mask) * CHAR_BIT - 1);
int digcount = 0;
while(mask)
{
printf("%d%s", !!(x & mask), ++digcount % 4 ? "" : " ");
mask >>= 1;
}
}
int main(void)
{
printBin(0); printf("\n");
printBin(1); printf("\n");
printBin(0xf0); printf("\n");
printBin(-10); printf("\n");
}

Create a 128 byte random number

If the rand() function creates a random number that is 4 bytes in length, and I wanted to create a random number that is 1024 bits in length (128 bytes), is the easiest method to get this by concatenating the rand() function 256 times or is there an alternative method?
#include <stdio.h>
#include <string.h>
int main(void) {
const char data[128];
memset(&data, 0x36, 128);
printf("%s\n", data);
puts("");
printf("%d\n", sizeof(data)/sizeof(data[0]));
puts("");
int i = 0;
unsigned long rez = 0;
for(i = 0; i < 20; i++) {
unsigned int num = rand();
rez = rez + num;
printf("%x\n", rez);
}
printf("%x\n", rez);
return 0;
}
is the easiest method to get this by concatenating the rand() function 256 times or is there an alternative method?
Each rand() returns a value in the [0...RAND_MAX] range. RAND_MAX is limited to 32767 <= RAND_MAX <= INT_MAX.
Very commonly RAND_MAX is a Mersenne number of the form 2n − 1. Code can take advantage of this this very common implementation dependent value. Each rand() call then provides RAND_MAX_BITS and not 32 as suggested by OP for a 4-byte int. #Matteo Italia
[See far below update]
#include <stdlib.h>
#if RAND_MAX == 0x7FFF
#define RAND_MAX_BITS 15
#elif RAND_MAX == 0x7FFFFFFF
#define RAND_MAX_BITS 31
#else
#error TBD code
#endif
Call rand() ⌈size * 8 / RAND_MAX_BITS⌉ times. This eases the number of rand() calls needed from size.
void rand_byte(uint8_t *dest, size_t size) {
int r_queue = 0;
int r_bit_count = 0;
for (size_t i = 0; i < size; i++) {
int r = 0;
//printf("%3zu %2d %8x\n", i, r_bit_count, r_queue);
if (r_bit_count < 8) {
int need = 8 - r_bit_count;
r = r_queue << need;
r_queue = rand();
r ^= r_queue; // OK to flip bits already saved in `r`
r_queue >>= need;
r_bit_count = RAND_MAX_BITS - need;
} else {
r = r_queue;
r_queue >>= 8;
r_bit_count -= 8;
}
dest[i] = r;
}
}
int main(void) {
uint8_t buf[128];
rand_byte(buf, sizeof buf);
...
return 0;
}
If you want the easiest bit less efficient code, simply call rand() for each byte as answered by #dbush
[Update 2021]
#Anonymous Question Guy posted a nifty macro that returns the bit width of a Mersenne number, more generally than the #if RAND_MAX == 0x7FFF approach above.
/* Number of bits in inttype_MAX, or in any (1<<b)-1 where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
_Static_assert((RAND_MAX & 1 && (RAND_MAX/2 + 1) & (RAND_MAX/2)) == 0,
"RAND_MAX is not a Mersenne number");
#define RAND_MAX_BITS IMAX_BITS(RAND_MAX)
The C standard states that RAND_MAX has a minimum value of 32767 (0x7fff), so it's best to work under that assumption.
Because the function will only return 15 random bits, using all the bits in one call will involve some bit shifting and masking to get the results in the proper place. The simplest way to do this would be to call rand 128 times, take the low order byte of each result, and write it to your byte array:
unsigned char rand_val[128];
for (int i=0; i<128; i++) {
rand_val[i] = rand() & 0xff;
}
Don't forget to call srand exactly once somewhere before this in your code.
Using strcat as you mentioned in your comment won't work because this function works on null terminated strings, and a byte containing 0 is a valid random number.
If you plan on using these random values for anything involving cryptography, you're better off using a secure random number generator. If you have OpenSSL available, use RAND_bytes for this purpose:
unsigned char rand_val[128];
RAND_bytes(rand_val, sizeof(rand_val));
On most POSIX (Unix-like) systems, you can also read 128 bytes from /dev/urandom which you would open like a regular file in binary mode — even though POSIX does not specify the device.
The properties of C rand() are vaguely specified by the standard; as said in a comment, the number of actual usable bits depends from implementation, and their quality has been historically plagued by sub-par implementations. Also, rand() affects the global state of the program and on many implementations is not thread safe.
Given that a there are good, known and simple PRNGs such as the ones from the XorShift family, I would just use one of them.
#include <stdint.h>
/* The state must be seeded so that it is not all zero */
uint64_t s[2];
uint64_t xorshift128plus(void) {
uint64_t x = s[0];
uint64_t const y = s[1];
s[0] = y;
x ^= x << 23;
s[1] = x ^ y ^ (x >> 17) ^ (y >> 26);
return s[1] + y;
}
void next128bits(unsigned char ch[16]) {
uint64_t t = xorshift128plus();
memcpy(ch, &t, sizeof(t));
t = xorshift128plus();
memcpy(ch + 8, &t, sizeof(t));
}

c, obtaining a special random number

I have a algorithm problem that I need to speed up :)
I need a 32bit random number, with exact 10 bits set to 1. But in the same time, patterns like 101 (5 dec) and 11 (3 dec) to be considered illegal.
Now the MCU is a 8051 (8 bit) and I tested all this in Keil uVision. My first attempt completes, giving the solution
0x48891249
1001000100010010001001001001001 // correct, 10 bits 1, no 101 or 11
The problem is that it completes in 97 Seconds or 1165570706 CPU cycles which is ridiculous!!!
Here is my code
// returns 1 if number is not good. ie. contains at leats one 101 bit sequence
bool checkFive(unsigned long num)
{
unsigned char tmp;
do {
tmp = (unsigned char)num;
if(
(tmp & 7) == 5
|| (tmp & 3) == 3
) // illegal pattern 11 or 101
return true; // found
num >>= 1;
}while(num);
return false;
}
void main(void) {
unsigned long v,num; // count the number of bits set in v
unsigned long c; // c accumulates the total bits set in v
do {
num = (unsigned long)rand() << 16 | rand();
v = num;
// count all 1 bits, Kernigen style
for (c = 0; v; c++)
v &= v - 1; // clear the least significant bit set
}while(c != 10 || checkFive(num));
while(1);
}
The big question for a brilliant mind :)
Can be done faster? Seems that my approach is naive.
Thank you in advance,
Wow, I'm impressed, thanks all for suggestions. However, before accept, I need to test them these days.
Now with the first option (look-up) it's just not realistic, will complete blow my 4K RAM of entire 8051 micro controller :) As you can see in image bellow, I tested for all combinations in Code Blocks but there are way more than 300 and it's not finished yet until 5000 index...
The code I use to test
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
//#define bool bit
//#define true 1
//#define false 0
// returns 1 if number is not good. ie. contains at leats one 101 bit sequence
bool checkFive(uint32_t num)
{
uint8_t tmp;
do {
tmp = (unsigned char)num;
if(
(tmp & 7) == 5
|| (tmp & 3) == 3
) // illegal pattern 11 or 101
return true; // found
num >>= 1;
}while(num);
return false;
}
void main(void) {
uint32_t v,num; // count the number of bits set in v
uint32_t c, count=0; // c accumulates the total bits set in v
//printf("Program started \n");
num = 0;
printf("Program started \n");
for(num=0; num <= 0xFFFFFFFF; num++)
{
//do {
//num = (uint32_t)rand() << 16 | rand();
v = num;
// count all 1 bits, Kernigen style
for (c = 0; v; c++)
v &= v - 1; // clear the least significant bit set
//}while(c != 10 || checkFive(num));
if(c != 10 || checkFive(num))
continue;
count++;
printf("%d: %04X\n", count, num);
}
printf("Complete \n");
while(1);
}
Perhaps I can re-formulate the problem:
I need a number with:
precise (known) amount of 1 bits, 10 in my example
not having 11 or 101 patterns
remaining zeroes can be any
So somehow, shuffle only the 1 bits inside.
Or, take a 0x00000000 and add just 10 of 1 bits in random positions, except the illegal patterns.
Solution
Given a routine r(n) that returns a random integer from 0 (inclusive) to n (exclusive) with uniform distribution, the values described in the question may be generated with a uniform distribution by calls to P(10, 4) where P is:
static uint32_t P(int a, int b)
{
if (a == 0 && b == 0)
return 0;
else
return r(a+b) < a ? P(a-1, b) << 3 | 1 : P(a, b-1) << 1;
}
The required random number generator can be:
static int r(int a)
{
int q;
do
q = rand() / ((RAND_MAX+1u)/a);
while (a <= q);
return q;
}
(The purpose of dividing by (RAND_MAX+1u)/a and the do-while loop is to trim the range of rand to an even multiple of a so that bias due to a non-multiple range is eliminated.)
(The recursion in P may be converted to iteration. This is omitted as it is unnecessary to illustrate the algorithm.)
Discussion
If the number cannot contain consecutive bits 11 or 101, then the closest together two 1 bits can be is three bits apart, as in 1001. Fitting ten 1 bits in 32 bits then requires at least 28 bits, as in 1001001001001001001001001001. Therefore, to satisfy the constraints that there is no 11 or 101 and there are exactly 10 1 bits, the value must be 1001001001001001001001001001 with four 0 bits inserted in some positions (including possibly the beginning or the end).
Selecting such a value is equivalent to placing 10 instances of 001 and 4 instances of 0 in some order.1 There are 14! ways of ordering 14 items, but any of the 10! ways of rearranging the 10 001 instances with each other are identical, and any of the 4! ways of rearranging the 0 instances with each other are identical, so the number of distinct selections is 14! / 10! / 4!, also known as the number of combinations of selecting 10 things from 14. This is 1,001.
To perform such a selection with uniform distribution, we can use a recursive algorithm:
Select the first choice with probability distribution equal to the proportion of the choices in the possible orderings.
Select the remaining choices recursively.
When ordering a instances of one object and b of a second object, a/(a+b) of the potential orderings will start with the first object, and b/(a+b) will start with the second object. Thus, the design of the P routine is:
If there are no objects to put in order, return the empty bit string.
Select a random integer in [0, a+b). If it is less than a (which has probability a/(a+b)), insert the bit string 001 and then recurse to select an order for a-1 instances of 001 and b instances of 0.
Otherwise, insert the bit string 0 and then recurse to select an order for a instances of 001 and b-1 instances of 0.
(Since, once a is zero, only 0 instances are generated, if (a == 0 && b == 0) in P may be changed to if (a == 0). I left it in the former form as that shows the general form of a solution in case other strings are involved.)
Bonus
Here is a program to list all values (although not in ascending order).
#include <stdint.h>
#include <stdio.h>
static void P(uint32_t x, int a, int b)
{
if (a == 0 && b == 0)
printf("0x%x\n", x);
else
{
if (0 < a) P(x << 3 | 1, a-1, b);
if (0 < b) P(x << 1, a, b-1);
}
}
int main(void)
{
P(0, 10, 4);
}
Footnote
1 This formulation means we end up with a string starting 001… rather than 1…, but the resulting value, interpreted as binary, is equivalent, even if there are instances of 0 inserted ahead of it. So the strings with 10 001 and 4 0 are in one-to-one correspondence with the strings with 4 0 inserted into 1001001001001001001001001001.
One way to satisfy your criteria in a limited number of solutions is to utilize the fact that there can be no more that four groups of 000s within the bit population. This also means that there can one be one group of 0000 in the value. Knowing this, you can seed your value with a single 1 in bits 27-31 and then continue adding random bits checking that each bit added satisfies your 3 or 5 constraints.
When adding random bits to your value and satisfying your constraints, there can always be combinations that lead to a solution that can never satisfy all constraints. To protect against those cases, just keep an iteration count and reset/restart the value generation if iterations exceed that value. Here, if a solution is going to be found, it will be found in less than 100 iterations. And is generally found in 1-8 attempts. Meaning for each value you generate, you have on average no more than 800 iterations which will be a far cry less than "97 Seconds or 1165570706 CPU cycles" (I haven't counted cycles, but the return is almost instantaneous)
There are many ways to approach this problem, this is just one that worked in a reasonable amount of time:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#define BPOP 10
#define NBITS 32
#define LIMIT 100
/** rand_int for use with shuffle */
static int rand_int (int n)
{
int limit = RAND_MAX - RAND_MAX % n, rnd;
rnd = rand();
for (; rnd >= limit; )
rnd = rand();
return rnd % n;
}
int main (void) {
int pop = 0;
unsigned v = 0, n = NBITS;
size_t its = 1;
srand (time (NULL));
/* one of first 5 bits must be set */
v |= 1u << (NBITS - 1 - rand_int (sizeof v + 1));
pop++; /* increment pop count */
while (pop < BPOP) { /* loop until pop count 10 */
if (++its >= LIMIT) { /* check iterations */
#ifdef DEBUG
fprintf (stderr, "failed solution.\n");
#endif
pop = its = 1; /* reset for next iteration */
v = 0;
v |= 1u << (NBITS - 1 - rand_int (sizeof v + 1));
}
unsigned shift = rand_int (NBITS); /* get random shift */
if (v & (1u << shift)) /* if bit already set */
continue;
/* protect against 5 (101) */
if ((shift + 2) < NBITS && v & (1u << (shift + 2)))
continue;
if ((int)(shift - 2) >= 0 && v & (1u << (shift - 2)))
continue;
/* protect against 3 (11) */
if ((shift + 1) < NBITS && v & (1u << (shift + 1)))
continue;
if ((int)(shift - 1) >= 0 && v & (1u << (shift - 1)))
continue;
v |= 1u << shift; /* add bit at shift */
pop++; /* increment pop count */
}
printf ("\nv : 0x%08x\n", v); /* output value */
while (n--) { /* output binary confirmation */
if (n+1 < NBITS && (n+1) % 4 == 0)
putchar ('-');
putchar ((v >> n & 1) ? '1' : '0');
}
putchar ('\n');
#ifdef DEBUG
printf ("\nits: %zu\n", its);
#endif
return 0;
}
(note: you will probably want a better random source like getrandom() or reading from /dev/urandom if you intend to generate multiple random solutions within a loop -- expecially if you are calling the executable in a loop from your shell)
I have also included a DEBUG define that you can enable by adding the -DDEBUG option to your compiler string to see the number of failed solutions and number of iterations on the final.
Example Use/Output
The results for 8 successive runs:
$ ./bin/randbits
v : 0x49124889
0100-1001-0001-0010-0100-1000-1000-1001
v : 0x49124492
0100-1001-0001-0010-0100-0100-1001-0010
v : 0x48492449
0100-1000-0100-1001-0010-0100-0100-1001
v : 0x91249092
1001-0001-0010-0100-1001-0000-1001-0010
v : 0x92488921
1001-0010-0100-1000-1000-1001-0010-0001
v : 0x89092489
1000-1001-0000-1001-0010-0100-1000-1001
v : 0x82491249
1000-0010-0100-1001-0001-0010-0100-1001
v : 0x92448922
1001-0010-0100-0100-1000-1001-0010-0010
As Eric mentioned in his answer, since each 1 but must be separated by at least two 0 bits, you basically start with the 28-bit pattern 1001001001001001001001001001. It's then a matter of placing the remaining four 0 bits within this bit pattern, and there are 11 distinct places to insert each zero.
This can be accomplished by first selecting a random number from 1 to 11 to determine where to place a bit. Then you left shift all the bits above the target bit by 1. Repeat 3 more times, and you have your value.
This can be done as follows:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
void binprint(uint32_t n)
{
int i;
for (i=0;i<32;i++) {
if ( n & (1u << (31 - i))) {
putchar('1');
} else {
putchar('0');
}
}
}
// inserts a 0 bit into val after pos "1" bits are found
uint32_t insert(uint32_t val, int pos)
{
int cnt = 0;
uint32_t mask = 1u << 31;
uint32_t upper, lower;
while (cnt < pos) {
if (val & mask) { // look for a set bit and count if you find one
cnt++;
}
mask >>= 1;
}
if (mask == (1u << 31)) {
return val; // insert at the start: no change
} else if (mask == 0) {
return val << 1; // insert at the end: shift the whole thing by 1
} else {
mask = (mask << 1) - 1; // mask has all bits below the target set
lower = val & mask; // extract the lower portion
upper = val & (~mask); // extract the upper portion
return (upper << 1) | lower; // recombine with the upper portion shifted 1 bit
}
}
int main()
{
int i;
uint32_t val = 01111111111; // hey look, a good use of octal!
srand(time(NULL));
for (i=0;i<4;i++) {
int p = rand() % 11;
printf("p=%d\n", p);
val = insert(val, p);
}
binprint(val);
printf("\n");
return 0;
}
Sample output for two runs:
p=3
p=10
p=9
p=0
01001001000100100100100100100010
...
p=3
p=9
p=3
p=1
10001001000010010010010010010001
Run time is negligible.
Since you don't want a lookup table here is the way:
Basically you have this number with 28 bits set to 0 and 1 in which you need to insert 4x 0 :
0b1001001001001001001001001001
Hence you can use the following algorithm:
int special_rng_nolookup(void)
{
int secret = 0b1001001001001001001001001001;
int low_secret;
int high_secret;
unsigned int i = 28; // len of secret
unsigned int rng;
int mask = 0xffff // equivalent to all bits set in integer
while (i < 32)
{
rng = __asm__ volatile(. // Pseudo code
"rdrand"
);
rng %= (i + 1); // will generate a number between 0 and 28 where you will add a 0. Then between 0 and 29, 30, 31 for the 3 next loop.
low_secret = secret & (mask >> (i - rng)); // locate where you will add your 0 and save the lower part of your number.
high_secret = (secret ^ low_secret) << (!(!rng)); // remove the lower part to your int and shift to insert a 0 between the higher part and the lower part. edit : if rng was 0 you want to add it at the very beginning (left part) so no shift.
secret = high_secret | low_secret; // put them together.
++i;
}
return secret;
}

Calculate dynamic range of rand with mod

I want to create a rand() range between 1 and the dynamic value of bit_cnt.
After reading more about the rand() function, I understand that out of the box rand() has a range of [0, RAND_MAX]. I also understand that RAND_MAX's value is library-dependent, but is guaranteed to be at least 32767.
I had to create a bit mask of 64 0s.
Now, I am trying to left shift the bit mask by a dynamic value of bit_cnt anded with the a randomly generated number of bits between 1 and the dynamic value of bit_cnt.
For example, when bit_cnt is 10, I want to randomize the lowest 10 bits.
Originally, I had
mask = (mask << bit_cnt) + (rand()% bit_cnt);
which caused a floating point exception. From what I am understanding, that exception occurred because the value of bit_cntbecame 0.
Therefore, I attempted to create an if statement like this:
if((rand()%bit_cnt))!=0){
mask = (mask << bit_cnt) + (rand()% bit_cnt);
}
,but the floating point exception still occurred.
Then I tried the following thinking that the value not be 0 so increase the value to at least 1:
mask = (mask << bit_cnt) + ((rand()% bit_cnt)+1);
,but the floating point exception still occurred.
Afterwards, I tried the following:
mask = (mask << bit_cnt) + (1+(rand()%(bit_cnt+1)));
and the following 20 lines of 64 bits outputted:
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000000011
0000000000000000000000000000000000000000000000000000000000000101
0000000000000000000000000000000000000000000000000000000000001010
0000000000000000000000000000000000000000000000000000000000010011
0000000000000000000000000000000000000000000000000000000000100011
0000000000000000000000000000000000000000000000000000000001000110
0000000000000000000000000000000000000000000000000000000010000100
0000000000000000000000000000000000000000000000000000000100001001
0000000000000000000000000000000000000000000000000000001000000010
0000000000000000000000000000000000000000000000000000010000000100
0000000000000000000000000000000000000000000000000000100000000111
0000000000000000000000000000000000000000000000000001000000000101
0000000000000000000000000000000000000000000000000010000000001001
0000000000000000000000000000000000000000000000000100000000000111
0000000000000000000000000000000000000000000000001000000000001111
0000000000000000000000000000000000000000000000010000000000001010
0000000000000000000000000000000000000000000000100000000000000101
0000000000000000000000000000000000000000000001000000000000001101
0000000000000000000000000000000000000000000010000000000000001100
What was the cause of the floating point exception? Is this how to dynamic create a range of the rand() function?
I appreciate any suggestions. Thank you.
UPDATE:
I changed the if statement to be the following:
if(bit_cnt !=0)
and then performed the rest of the logic.
I received the following output:
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000000100
0000000000000000000000000000000000000000000000000000000000001000
0000000000000000000000000000000000000000000000000000000000010010
0000000000000000000000000000000000000000000000000000000000100001
0000000000000000000000000000000000000000000000000000000001000100
0000000000000000000000000000000000000000000000000000000010000110
0000000000000000000000000000000000000000000000000000000100000011
0000000000000000000000000000000000000000000000000000001000000000
0000000000000000000000000000000000000000000000000000010000001000
0000000000000000000000000000000000000000000000000000100000000111
0000000000000000000000000000000000000000000000000001000000000110
0000000000000000000000000000000000000000000000000010000000000110
0000000000000000000000000000000000000000000000000100000000001100
0000000000000000000000000000000000000000000000001000000000000010
0000000000000000000000000000000000000000000000010000000000001101
0000000000000000000000000000000000000000000000100000000000000110
0000000000000000000000000000000000000000000001000000000000010000
0000000000000000000000000000000000000000000010000000000000000100
Is there any possible way to know if the range is correct? Like is there any possible way to know by looking at the output?
const int LINE_CNT = 20;
void print_bin(uint64_t num, unsigned int bit_cnt);
uint64_t rand_bits(unsigned int bit_cnt);
int main(int argc, char *argv[]) {
int i;
srand(time(NULL));
for(i = 0; i < LINE_CNT; i++) {
uint64_t val64 = rand_bits(i);
print_bin(val64, 64);
}
return EXIT_SUCCESS;
}
void print_bin(uint64_t num, unsigned int bit_cnt) {
int top_bit_cnt;
if(bit_cnt <= 0) return;
if(bit_cnt > 64) bit_cnt = 64;
top_bit_cnt = 64;
while(top_bit_cnt > bit_cnt) {
top_bit_cnt--;
printf(" ");
}
while(bit_cnt > 0) {
bit_cnt--;
printf("%d", (num & ((uint64_t)1 << bit_cnt)) != 0);
}
printf("\n");
return;
}
uint64_t rand_bits(unsigned int bit_cnt) {
uintmax_t mask = 1;
if (bit_cnt != 0) {
mask = (mask << bit_cnt) + (rand()% bit_cnt);
}
return mask;
}
I am trying to modify the function rand_bits to return all 0 expect for the lowest bits aka bit_cnt which are randomized.
Returns a 64 bit pattern with all zeros except for the lowest requested bits, which are randomized. This allows for arbitrary length random bit patterns in a portable fashion as the C standard "rand()" function is only required to return
random numbers between 0 and 32767... effectively, a random 15 bit pattern.
Parameter, "bit_cnt": How many of the lowest bits, including the lowest order bit (bit 0) to be randomized.
UPDATE: Added Barmar's newest suggestion of mask = rand() % (1 << bit_cnt);:
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000001000
0000000000000000000000000000000000000000000000000000000000001001
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000010101
0000000000000000000000000000000000000000000000000000000001001111
0000000000000000000000000000000000000000000000000000000010000011
0000000000000000000000000000000000000000000000000000001010101001
0000000000000000000000000000000000000000000000000000010101101100
0000000000000000000000000000000000000000000000000000101011111000
0000000000000000000000000000000000000000000000000001001010101111
0000000000000000000000000000000000000000000000000011101011000101
0000000000000000000000000000000000000000000000000001001101111101
0000000000000000000000000000000000000000000000001111000000111010
0000000000000000000000000000000000000000000000000101100000001100
0000000000000000000000000000000000000000000000100111101000111111
0000000000000000000000000000000000000000000001010101011101000110
uint64_t rand_bits(unsigned int bit_cnt) {
uintmax_t mask = 1;
if (bit_cnt != 0) {
mask = rand() % (1 << bit_cnt);
}
return mask;
}
The problem is that anything % bit_cnt will get an error if bit_cnt is 0. You need to check bit_cnt before you try to perform the modulus.
if (bit_cnt != 0) {
mask = (mask << bit_cnt) + (rand()% bit_cnt) + 1;
}
All your attempts performed the modulus and then tried to do something with the result, but that's after the error happens.
This uses the bit count to generate a mask. If you want a bit count greater than can be filled by RAND_MAX, implement another random function as I commented earlier.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int bit_cnt = 10;
unsigned mask = 0;
int i;
int num;
srand((unsigned)time(NULL));
for(i = 0; i < bit_cnt; i++)
mask = (mask << 1) | 1;
printf ("For bit_cnt=%d, mask=0x%X\n\n", bit_cnt, mask);
for (i = 0; i < 5; i++) {
num = rand() & mask;
printf("Random number 0x%0*X\n", 1+(bit_cnt-1)/4, num);
}
}
Program output:
For bit_cnt=10, mask=0x3FF
Random number 0x327
Random number 0x39C
Random number 0x1B1
Random number 0x088
Random number 0x26E

Efficient computation of greatest power of 2 < x [duplicate]

This question already has answers here:
Find most significant bit (left-most) that is set in a bit array
(17 answers)
Compute fast log base 2 ceiling
(15 answers)
Closed 9 years ago.
I have a requirement to compute the greatest power of 2 which is < an integer value, x
currently I am using:
#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)
x = round(pow(2,(ceil(log2(n))-1)));
this is in a performance critical function
Is there a more computationally efficient way of calculating x?
You are essentially looking for the highest non-zero bit in your number. Many processors have built-in instructions for this, which in turn are exposed by many compilers. For example, in GCC I would look at __builtin_clz, which
Returns the number of leading 0-bits in x, starting at the most significant bit position.
Together with sizeof(int) * CHAR_BIT and a shift, you can use this to figure out the corresponding pure-power-of-two integer. There's also a version for long integers.
(The CPU instruction is presumably called "CLZ" (count leading zeros), in case you need to look this up for other compilers.)
I have an integer log2 function in my c-libutl library (hosted on googlecode if anyone is interested)
/*
** Integer log base 2 of a 32 bits integer values.
** llog2(0) == llog2(1) == 0
*/
unsigned short llog2(unsigned long x)
{
long l = 0;
x &= 0xFFFFFFFF /* just in case 'long' is more than 32bit */
if (x==0) return 0;
#ifndef UTL_NOASM
#if defined(__POCC__) || defined(_MSC_VER) || defined (__WATCOMC__)
/* Pelles C MS Visual C++ OpenWatcom */
__asm { mov eax, [x]
bsr ecx, eax
mov l, ecx
}
#elif defined(__GNUC__)
l = (unsigned short) ((sizeof(long)*8 -1) - __builtin_clzl(x));
#else
#define UTL_NOASM
#endif
#endif
#ifdef UTL_NOASM /* Make a binary search.*/
if (x & 0xFFFF0000) {l += 16; x >>= 16;} /* 11111111111111110000000000000000 */
if (x & 0xFF00) {l += 8; x >>= 8 ;} /* 1111111100000000*/
if (x & 0xF0) {l += 4; x >>= 4 ;} /* 11110000*/
if (x & 0xC) {l += 2; x >>= 2 ;} /* 1100 */
if (x & 2) {l += 1; } /* 10 */
return l;
#endif
return (unsigned short)l;
}
Then you can simply compute
(1 << llog2(x))
to compute the greatest power of two that is less than x. Beware 0! You should handle it separately.
It uses assembler code but can also be forced to plain C code by defining the UTL_NOASM symbol.
The code has been tested at the time but it's quite some time I don't use it and I can't say if it behaves in a 64-bit environment.
Based on Bit Twiddling Hacks: Find the log base 2 of an N-bit integer in O(lg(N)) operations by Sean Eron Anderson (code contributed by Eric Cole and Andrew Shapira):
unsigned int highest_bit (uint32_t v) {
unsigned int r = 0, s;
s = (v > 0xFFFF) << 4; v >>= s; r |= s;
s = (v > 0xFF ) << 3; v >>= s; r |= s;
s = (v > 0xF ) << 2; v >>= s; r |= s;
s = (v > 0x3 ) << 1; v >>= s; r |= s;
return r | (v >> 1);
}
This returns the index of the highest bit of the input; the greatest power of 2 no greater than the input is then 1 << highest_bit(x), and the greatest power of 2 strictly less than the input is thus simply 1 << highest_bit(x-1).
For 64-bit inputs, just change the input type to uint64_t and add the following extra line at the beginning of the function, after the variable declarations:
s = (v > 0xFFFFFFFF) << 8; v >>= s; r |= s;
Left and right shift operators do this the best
int MaxPowerOf2(int x)
{
int out = 1;
while(x > 1) { x>>1; out<<1;}
return out;
}
#include <math.h>
double greatestPower( double x )
{
return floor(log( x ) / log( 2 ));
}
That is true since log in monotony increasing function.
Shifting bits around will most likely be much faster. Probably some bisection method on bits could make it even faster. Nice exercise for an improvement.
#include <stdio.h>
int closestPow2(int x)
{
int p;
if (x <= 1) return 0; /* No such power exists */
x--; /* Account for exact powers of 2, then one power less must be returned */
for (p = 0; x > 0; p++)
{
x >>= 1;
}
return 1<<(p-1);
}
int main(void)
{
printf("%x\n", closestPow2(0x7FFFFFFF));
return 0;
}

Resources