I'm trying to make a get_random_4digit function that generates a 4 digit number that has non-repeating digits ranging from 1-9 while only using ints, if, while and functions, so no arrays etc.
This is the code I have but it is not really working as intended, could anyone point me in the right direction?
int get_random_4digit() {
int d1 = rand() % 9 + 1;
int d2 = rand() % 9 + 1;
while (true) {
if (d1 != d2) {
int d3 = rand() % 9 + 1;
if (d3 != d1 || d3 != d2) {
int d4 = rand() % 9 + 1;
if (d4 != d1 || d4 != d2 || d4 != d3) {
random_4digit = (d1 * 1000) + (d2 * 100) + (d3 * 10) + d4;
break;
}
}
}
}
printf("Random 4digit = %d\n", random_4digit);
}
A KISS-approach could be this:
int getRandom4Digits() {
uint16_t acc = 0;
uint16_t used = 0;
for (int i = 0; i < 4; i++) {
int idx;
do {
idx = rand() % 9; // Not equidistributed but never mind...
} while (used & (1 << idx));
acc = acc * 10 + (idx + 1);
used |= (1 << idx);
}
return acc;
}
This looks terribly dumb at first. A quick analysis gives that this really isn't so bad, giving a number of calls to rand() to be about 4.9.
The expected number of inner loop steps [and corresponding calls to rand(), if we assume rand() % 9 to be i.i.d.] will be:
9/9 + 9/8 + 9/7 + 9/6 ~ 4.9107.
There are 9 possibilities for the first digit, 8 possibilities for the second digit, 7 possibilities for the third digit and 6 possibilities for the last digit. This works out to "9*8*7*6 = 3024 permutations".
Start by getting a random number from 0 to 3023. Let's call that P. To do this without causing a biased distribution use something like do { P = rand() & 0xFFF; } while(P >= 3024);.
Note: If you don't care about uniform distribution you could just do P = rand() % 3024;. In this case lower values of P will be more likely because RAND_MAX doesn't divide by 3024 nicely.
The first digit has 9 possibilities, so do d1 = P % 9 + 1; P = P / 9;.
The second digit has 8 possibilities, so do d2 = P % 8 + 1; P = P / 8;.
The third digit has 7 possibilities, so do d3 = P % 7 + 1; P = P / 7;.
For the last digit you can just do d4 = P + 1; because we know P can't be too high.
Next; convert "possibility" into a digit. For d1 you do nothing. For d2 you need to increase it if it's greater than or equal to d1, like if(d2 >= d1) d2++;. Do the same for d3 and d4 (comparing against all previous digits).
The final code will be something like:
int get_random_4digit() {
int P, d1, d2, d3, d4;
do {
P = rand() & 0xFFF;
} while(P >= 3024);
d1 = P % 9 + 1; P = P / 9;
d2 = P % 8 + 1; P = P / 8;
d3 = P % 7 + 1; P = P / 7;
d4 = P + 1;
if(d2 >= d1) d2++;
if(d3 >= d1) d3++;
if(d3 >= d2) d3++;
if(d4 >= d1) d4++;
if(d4 >= d2) d4++;
if(d4 >= d3) d4++;
return d1*1000 + d2*100 + d3*10 + d4;
}
You could start with an integer number, 0x123456789, and pick random nibbles from it (the 4 bits that makes up one of the digits in the hex value). When a nibble has been selected, remove it from the number and continue picking from those left.
This makes exactly 4 calls to rand() and has no if or other conditions (other than the loop condition).
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int get_random_4digit() {
uint64_t bits = 0x123456789; // nibbles
int res = 0;
// pick random nibbles
for(unsigned last = 9 - 1; last > 9 - 1 - 4; --last) {
unsigned lsh = last * 4; // shift last nibble
unsigned sel = (rand() % (last + 1)) * 4; // shift for random nibble
// multiply with 10 and add the selected nibble
res = res * 10 + ((bits & (0xFULL << sel)) >> sel);
// move the last unselected nibble right to where the selected
// nibble was:
bits = (bits & ~(0xFULL << sel)) |
((bits & (0xFULL << lsh)) >> (lsh - sel));
}
return res;
}
Demo
Another variant could be to use the same value, 0x123456789, and do a Fisher-Yates shuffle on the nibbles. When the shuffle is done, return the 4 lowest nibbles. This is more expensive since it randomizes the order of all 9 nibbles - but it makes it easy if you want to select an arbitrary amount of them afterwards.
Example:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
uint16_t get_random_4digit() {
uint64_t bits = 0x123456789; // nibbles
// shuffle the nibbles
for(unsigned idx = 9 - 1; idx > 0; --idx) {
unsigned ish = idx * 4; // index shift
// shift for random nibble to swap with `idx`
unsigned swp = (rand() % (idx + 1)) * 4;
// extract the selected nibbles
uint64_t a = (bits & (0xFULL << ish)) >> ish;
uint64_t b = (bits & (0xFULL << swp)) >> swp;
// swap them
bits &= ~((0xFULL << ish) | (0xFULL << swp));
bits |= (a << swp) | (b << ish);
}
return bits & 0xFFFF; // return the 4 lowest nibbles
}
The bit manipulation can probably be optimized - but I wrote it like I thought it so it's probably better for readability to leave it as-is
You can then print the value as a hex value to get the output you want - or extract the 4 nibbles and convert it for decimal output.
int main() {
srand(time(NULL));
uint16_t res = get_random_4digit();
// print directly as hex:
printf("%X\n", res);
// or extract the nibbles and multiply to get decimal result - same output:
uint16_t a = (res >> 12) & 0xF;
uint16_t b = (res >> 8) & 0xF;
uint16_t c = (res >> 4) & 0xF;
uint16_t d = (res >> 0) & 0xF;
uint16_t dec = a * 1000 + b * 100 + c * 10 + d;
printf("%d\n", dec);
}
Demo
You should keep generating digits until distinct one found:
int get_random_4digit() {
int random_4digit = 0;
/* We must have 4 digits number - at least 1234 */
while (random_4digit < 1000) {
int digit = rand() % 9 + 1;
/* check if generated digit is not in the result */
for (int number = random_4digit; number > 0; number /= 10)
if (number % 10 == digit) {
digit = 0; /* digit has been found, we'll try once more */
break;
}
if (digit > 0) /* unique digit generated, we add it to result */
random_4digit = random_4digit * 10 + digit;
}
return random_4digit;
}
Please, fiddle youself
One way to do this is to create an array with all 9 digits, pick a random one and remove it from the list.
Something like this:
uint_fast8_t digits[]={1,2,3,4,5,6,7,8,9}; //only 1-9 are allowed, 0 is not allowed
uint_fast8_t left=4; //How many digits are left to create
unsigned result=0; //Store the 4-digit number here
while(left--)
{
uint_fast8_t digit=getRand(9-4+left); //pick a random index
result=result*10+digits[digit];
//Move all digits above the selcted one 1 index down.
//This removes the picked digit from the array.
while(digit<8)
{
digits[digit]=digits[digit+1];
digit++;
}
}
You said you need a solution without arrays. Luckily, we can store up to 16 4 bit numbers in a single uint64_t. Here is an example that uses a uint64_t to store the digit list so that no array is needed.
#include <stdint.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
unsigned getRand(unsigned max)
{
return rand()%(max+1);
}
//Creates a uint64_t that is used as an array.
//Use no more than 16 values and don't use values >0x0F
//The last argument will have index 0
uint64_t fakeArrayCreate(uint_fast8_t count, ...)
{
uint64_t result=0;
va_list args;
va_start (args, count);
while(count--)
{
result=(result<<4) | va_arg(args,int);
}
return result;
}
uint_fast8_t fakeArrayGet(uint64_t array, uint_fast8_t index)
{
return array>>(4*index)&0x0F;
}
uint64_t fakeArraySet(uint64_t array, uint_fast8_t index, uint_fast8_t value)
{
array = array & ~((uint64_t)0x0F<<(4*index));
array = array | ((uint64_t)value<<(4*index));
return array;
}
unsigned getRandomDigits(void)
{
uint64_t digits = fakeArrayCreate(9,9,8,7,6,5,4,3,2,1);
uint_fast8_t left=4;
unsigned result=0;
while(left--)
{
uint_fast8_t digit=getRand(9-4+left);
result=result*10+fakeArrayGet(digits,digit);
//Move all digits above the selcted one 1 index down.
//This removes the picked digit from the array.
while(digit<8)
{
digits=fakeArraySet(digits,digit,fakeArrayGet(digits,digit+1));
digit++;
}
}
return result;
}
//Test our function
int main(int argc, char **argv)
{
srand(atoi(argv[1]));
printf("%u\n",getRandomDigits());
}
You could use a partial Fisher-Yates shuffle on an array of 9 digits, stopping after 4 digits:
// Return random integer from 0 to n-1
// (for n in range 1 to RAND_MAX+1u).
int get_random_int(unsigned int n) {
unsigned int x = (RAND_MAX + 1u) / n;
unsigned int limit = x * n;
int s;
do {
s = rand();
} while (s >= limit);
return s / x;
}
// Return random 4-digit number from 1234 to 9876 with no
// duplicate digits and no 0 digit.
int get_random_4digit(void) {
char possible[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int result = 0;
int i;
// Uses partial Fisher-Yates shuffle.
for (i = 0; i < 4; i++) {
// Get random position rand_pos from remaining possibilities i to 8
// (positions before i contain previous selected digits).
int rand_pos = i + get_random_int(9 - i);
// Select digit from position rand_pos.
char digit = possible[rand_pos];
// Exchange digits at positions i and rand_pos.
possible[rand_pos] = possible[i];
possible[i] = digit; // not really needed
// Put selected digit into result.
result = result * 10 + digit;
}
return result;
}
EDIT: I forgot the requirement "while only using int's, if, while and functions, so no arrays etc.", so feel free to ignore this answer!
If normal C integer types are allowed including long long int, the get_random_4digit() function above can be replaced with the following to satisfy the requirement:
// Return random 4-digit number from 1234 to 9876 with no
// duplicate digits and no 0 digit.
int get_random_4digit(void) {
long long int possible = 0x123456789; // 4 bits per digit
int result = 0;
int i;
// Uses partial Fisher-Yates shuffle.
i = 0;
while (i < 4) {
// Determine random position rand_pos in remaining possibilities 0 to 8-i.
int rand_pos = get_random_int(9 - i);
// Select digit from position rand_pos.
int digit = (possible >> (4 * rand_pos)) & 0xF;
// Replace digit at position rand_pos with digit at position 0.
possible ^= ((possible ^ digit) & 0xF) << (4 * rand_pos);
// Shift remaining possible digits down one position.
possible >>= 4;
// Put selected digit into result.
result = result * 10 + digit;
i++;
}
return result;
}
There are multiple answers to this question already, but none of them seem to fit the requirement only using ints, if, while and functions. Here is a modified version of Pelle Evensen's simple solution:
#include <stdlib.h>
int get_random_4digit(void) {
int acc = 0, used = 0, i = 0;
while (i < 4) {
int idx = rand() % 9; // Not strictly uniform but never mind...
if (!(used & (1 << idx))) {
acc = acc * 10 + idx + 1;
used |= 1 << idx;
i++;
}
}
return acc;
}
Related
I want to "convert" a decimal number to a hex number. Not like 10 -> A.
E.g.: 10 -> 0x10, 55 -> 0x55, 2021 -> 0x2021, ...
My input is an int.
I already heard something about it. You can get the first digit with modulo 10. E.g. 55 % 10 is 5. But I don't know how to get the other digits and how to put it together.
I am using this function for other purpose but I did some changes and its work fine.
you can use this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define CHECK_ALPHA_HEX(REC_CHAR) (unsigned)('#' < REC_CHAR && REC_CHAR < 'G')
#define CHECK_NUM(REC_CHAR) (unsigned)('/' < REC_CHAR && REC_CHAR < ':')
void DEC_TO_HEX(int in, int *outval ) {
uint8_t tbuff[5];
uint8_t chr_count = 0;
uint8_t len = sprintf(tbuff,"%d",in);
while(chr_count < len) {
tbuff[chr_count] -= CHECK_NUM(tbuff[chr_count]) ? '0' : CHECK_ALPHA_HEX(tbuff[chr_count]) ? '7' : tbuff[chr_count];
*outval |= (tbuff[chr_count] << (4 *((len-1) - chr_count)));
chr_count++;
}
}
int main() {
int out = 0;
int in = 2021;
DEC_TO_HEX(in,&out);`
printf("%x",out);
}
https://godbolt.org/z/8T9Wqb87n
how to get the other digits
Remove the extracted digit from input.
Repeat the extraction of one digit, until there are no more digits in input.
how to put it together.
Learn C programming language. Write a program that implements the algorithm.
As I understand, an integer value has to be converted to another integer. From there it's just basic arithmetic, where the process generatally consists of:
Getting one digit from input.
Putting it in output.
Removing that digit from input.
shifting input & output to desired state
I came up with 3 separate such convert_* function implementations. First one is similar to common simple int->string conversion algorithms - it first converts the digits and that the results is "inverted". The second one extract the digits from propor position from input - getting the most significant base10 digit from input and moving between base10 digits of input. The third one, puts base10 digits on the end of hex number (startign from the mast significant base16 digit), and then shifts hex number to the right to handle 0x55000000 trailing zeros in result.
#include <limits.h>
#include <stdio.h>
const unsigned maxhexdigits = sizeof(unsigned) * CHAR_BIT / 4;
unsigned convert_andrevert(unsigned n) {
unsigned o = 0;
unsigned hexdigits = 0;
// Convert hex digits from "the back"
while (n && hexdigits != maxhexdigits) {
o <<= 4;
o += n % 10;
n /= 10;
++hexdigits;
}
const unsigned swaps = hexdigits / 2;
//printf("a %#x %d %d \n", o, hexdigits, swaps);
// Invert hex digits
for (unsigned i = 0; i < swaps; ++i) {
const unsigned m1 = 0xFu << (i * 4);
const unsigned m2 = 0xFu << ((hexdigits - i - 1) * 4);
const unsigned road = (hexdigits - i * 2 - 1) * 4;
// extract bits m1
unsigned t = (o & m1) << road;
//printf("b o=%#x i=%#x 1=%#x m2=%#x t=%#x road=%d\n", o, i, m1, m2, t, road);
// set bit m1 in place of m2
o = (o & ~m1) | ((o & m2) >> road);
// set bit m2 in place of m1
o = (o & ~m2) | t;
}
return o;
}
unsigned mypow10u(unsigned i) {
unsigned r = 1;
while (i--) {
r *= 10;
}
return r;
}
unsigned convert_frommax(unsigned n) {
n %= mypow10u(maxhexdigits);
unsigned o = 0;
// always start from the maximuim digit, because
// we know it's location.
for (int i = maxhexdigits - 1; i >= 0; --i) {
o <<= 4;
//printf("o=%#x u=%d pow10u(i)=%u digit=%u rest=%u\n",
//o, i, mypow10u(i),
//n / mypow10u(i),
//n % mypow10u(i));
// extract leading base10 digit
o += n / mypow10u(i);
n %= mypow10u(i);
}
return o;
}
unsigned convert_andshift(unsigned n) {
unsigned o = 0;
unsigned hexdigits = 0;
// Convert hex digits from "the back"
// put put them from the front.
while (n && hexdigits != maxhexdigits) {
o >>= 4;
o += (n % 10) << (maxhexdigits * 4 - 4);
//printf("o=%#x %d\n", o, n%10);
n /= 10;
++hexdigits;
}
// Shift right to handle leading (trailing?) zeros.
o >>= ((maxhexdigits - hexdigits) * 4);
return o;
}
void testin(unsigned r, unsigned rr) {
printf(" -> %#x %s", rr, r == rr ? "OK" : "FAIL");
}
void TEST(unsigned a, unsigned r) {
printf("%u", a);
testin(r, convert_andrevert(a));
testin(r, convert_frommax(a));
testin(r, convert_andshift(a));
printf("\n");
}
int main() {
TEST(1, 0x1);
TEST(55, 0x55);
TEST(123, 0x123);
TEST(2021, 0x2021);
TEST(12345678, 0x12345678);
}
From basic profiling, convert_andshift is the fastest function.
Here is an approach:
#include<stdio.h>
int main()
{
int num = 0;
char cNumHex[20];
puts("Enter a decimal formed hex number: ");
scanf("%d",&num);
sprintf(cNumHex, "0x%d", num);
printf("\nThe entered as hex: %s\n", cNumHex);
return 0;
}
The output:
Enter a decimal formed hex number:
49478
The entered as hex: 0x49478
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;
}
I program that I would like to convert an array of big-endian (I believe that since I'm on a Mac, ints would be little-endian) chars (or rather uint8_ts) to an int64_t and back. Here is my code:
int64_t CharsToInt(uint8_t* chars) {
return chars[0] + (chars[1] * 0x100) + (chars[2] * 0x10000) + (chars[3] * 0x1000000) + (chars[4] * 0x100000000) + (chars[5] * 0x10000000000) + (chars[6] * 0x1000000000000) + (chars[7] * 0x100000000000000);
}
void IntToChars(int64_t i, uint8_t* chars) {
for(int k = 0; k < 8; k++) {
chars[k] = i >> k*8;
}
}
int main() {
int64_t x;
unsigned char chars[8];
IntToChars(x, chars);
for (int k = 0; k < 8; k++) {
printf("%0x\n", chars[k]);
}
// little endian
int64_t rv = CharsToInt(chars);
printf("%lld\n", rv);
}
If x is 12, or any other zero or positive number, the code works perfectly fine, however if x is a negative number, it fails to work.
Output for x = 12:
c
0
0
0
0
0
0
0
value: 12
output for x = -12:
f4
ff
ff
ff
ff
ff
ff
ff
value: -4294967308
This seems to have something to do with the way the sign gets stored and converted, because I think Intel (I'm on a Mac) uses 2s-compliment instead of a plain old sign bit. However, I don't really know how to determine if this is true, and if it is, how to compensate for it (preferably in a portable way).
I know that there are a lot of other questions like this, and I've read through them (in fact most of this code is from them), but I still can't get it to work, so I asked my own.
You are right. Intel 64 and IA-32 use 2 complement representation of signed numbers. See Intel 64 and IA-32 Architectures Software Developer’s Manual Section 4.2.1. Reading FFFFFFFFFFFFFFF4 for -12 is therefore correct. In the 2 complement representation negative numbers are represented by taking the corresponding positive, inverting all the bits and adding 1:
12 = 000000000000000C -> FFFFFFFFFFFFFFF3 -> FFFFFFFFFFFFFFF4 = -12
If I can add something, you chould convert your char array to an uint64_t also by doing:
int64_t CharsToInt(uint8_t* chars) {
return *(int64_t*)chars;
}
After messing around with it some more, this is what I finally got working (I think). It actually avoids having to deal with endianness and 2s-compliment all together, by removing the sign and reapplying it after the conversion, using C masks and multiplication:
int64_t CharsToInt(uint8_t* chars) {
// Don't modify argument
uint8_t tmp;
tmp = chars[0];
bool neg = false;
if (tmp & 0x80) {
tmp &= 0x7f;
neg = true;
}
int64_t rv = chars[7] + (chars[6] * 0x100) + (chars[5] * 0x10000) + (chars[4] * 0x1000000) + (chars[3] * 0x100000000) + (chars[2] * 0x10000000000) + (chars[1] * 0x1000000000000) + (tmp * 0x100000000000000);
if (neg) {
rv *= -1;
}
return rv;
}
void IntToChars(int64_t i, uint8_t* chars) {
int64_t num = i;
bool neg = false;
if (i & 0x8000000000000000) {
neg = true;
num *= -1;
}
chars[0] = num / 0x100000000000000;
num = num % 0x100000000000000;
chars[1] = num / 0x1000000000000;
num = num % 0x1000000000000;
chars[2] = num / 0x10000000000;
num = num % 0x10000000000;
chars[3] = num / 0x100000000;
num = num % 0x100000000;
chars[4] = num / 0x1000000;
num = num % 0x1000000;
chars[5] = num / 0x10000;
num = num % 0x10000;
chars[6] = num / 0x100;
num = num % 0x100;
chars[7] = num;
if (neg) {
chars[0] += 0x80;
}
}
There is an algorithm for a FIR filter but it's floatingpoint:
FIR filter implementation in C programming
If I want a fixedpoint algorithm with this spec, how would I do it?
the FIR-filter receives and sends 8-bit fixed-point numbers in the
Q7-format via the standard input and output. Remember to output the
measured time (number of ticks) also in hex format. Following the
guidelines presented in the previous section, your program should call
getchar() to read a Q7-value. should call putchar() to write a
Q7-value.
The coefficients are
c0=0.0299 c1=0.4701 c2=0.4701 c3=0.299
And for a fixedpoint algorithm I would need to implement my own multiplication for fixedpoint number, right?
Should I store a fixepdpoint number like a struct i.e.
struct point
{
int integer;
int fraction;
};
Should I use shifts to implement the numbering and specifically how?
The number are 32-bit so could I write the shifts like below?
#define SHIFT_AMOUNT 16 // 2^16 = 65536
#define SHIFT_MASK ((1 << SHIFT_AMOUNT) - 1)
So I think that I must implement one multiplication algorithm and then the FIR algorithm itself? Is that correct? Can you help me?
Update
I compiled and ran a program like in the anser but it's giving me unexpected output.
#include <stdio.h>
#include "system.h"
#define FBITS 16 /* number of fraction bits */
const int c0 = (( 299<<FBITS) + 5000) / 10000; /* (int)(0.0299*(1<<FBITS) + 0.5) */
const int c1 = ((4701<<FBITS) + 5000) / 10000; /* (int)(0.4701*(1<<FBITS) + 0.5) */
/* Ditto for C3 and C2 */
const int c2 = (( 4701<<FBITS) + 5000) / 10000; /* (int)(0.4701 *(1<<FBITS) + 0.5) */
const int c3 = ((299<<FBITS) + 5000) / 10000; /* (int)(0.299*(1<<FBITS) + 0.5) */
#define HALF (1 << (FBITS) >> 1) /* Half adjust for rounding = (int)(0.5 * (1<<FBITS)) */
signed char input[4]; /* The 4 most recent input values */
int output = 0;
void firFixed()
{
signed char sum = c0*input[0] + c1*input[1] + c2*input[2] + c3*input[3];
output = (signed char)((sum + HALF) >> FBITS);
printf("output: %d\n", output);
}
int main( void )
{
int i=0;
signed char inVal;
while (scanf("%c", &inVal) > 0)
{
if (i>3)
{
i=0;
}
input[i]=inVal;
firFixed();
i++;
}
return 0;
}
Why is output not computed correctly andd why is output written several times after one input?
Update
I tried writing the fixedpoint FIR filter, the algorithm might not be 100 % correct:
#include <stdio.h>
#include "system.h"
#define FBITS 16 /* number of fraction bits */
const int c0 = (( 299<<FBITS) + 5000) / 10000; /* (int)(0.0299*(1<<FBITS) + 0.5) */
const int c1 = ((4701<<FBITS) + 5000) / 10000; /* (int)(0.4701*(1<<FBITS) + 0.5) */
/* Ditto for C3 and C2 */
const int c2 = (( 4701<<FBITS) + 5000) / 10000; /* (int)(0.4701 *(1<<FBITS) + 0.5) */
const int c3 = ((299<<FBITS) + 5000) / 10000; /* (int)(0.299*(1<<FBITS) + 0.5) */
#define HALF (1 << (FBITS) >> 1) /* Half adjust for rounding = (int)(0.5 * (1<<FBITS)) */
signed char input[4]; /* The 4 most recent input values */
char get_q7( void );
void put_q7( char );
void firFixed()
{
int sum = c0*input[0] + c1*input[1] + c2*input[2] + c3*input[3];
signed char output = (signed char)((sum + HALF) >> FBITS);
put_q7(output);
}
int main( void )
{
int i=0;
while(1)
{
if (i>3)
{
i=0;
}
input[i]=get_q7();
firFixed();
i++;
}
return 0;
}
#include <sys/alt_stdio.h>
char get_q7( void );
char prompt[] = "Enter Q7 (in hex-code): ";
char error1[] = "Illegal hex-code - character ";
char error2[] = " is not allowed";
char error3[] = "Number too big";
char error4[] = "Line too long";
char error5[] = "Line too short";
char get_q7( void )
{
int c; /* Current character */
int i; /* Loop counter */
int num;
int ok = 0; /* Flag: 1 means input is accepted */
while( ok == 0 )
{
num = 0;
for( i = 0; prompt[i]; i += 1 )
alt_putchar( prompt[i] );
i = 0; /* Number of accepted characters */
while( ok == 0 )
{
c = alt_getchar();
if( c == (char)26/*EOF*/ ) return( -1 );
if( (c >= '0') && (c <= '9') )
{
num = num << 4;
num = num | (c & 0xf);
i = i + 1;
}
else if( (c >= 'A') && (c <= 'F') )
{
num = num << 4;
num = num | (c + 10 - 'A');
i = i + 1;
}
else if( (c >= 'a') && (c <= 'f') )
{
num = num << 4;
num = num | (c + 10 - 'a');
i = i + 1;
}
else if( c == 10 ) /* LF finishes line */
{
if( i > 0 ) ok = 1;
else
{ /* Line too short */
for( i = 0; error5[i]; i += 1 )
alt_putchar( error5[i] );
alt_putchar( '\n' );
break; /* Ask for a new number */
}
}
else if( (c & 0x20) == 'X' || (c < 0x20) )
{
/* Ignored - do nothing special */
}
else
{ /* Illegal hex-code */
for( i = 0; error1[i]; i += 1 )
alt_putchar( error1[i] );
alt_putchar( c );
for( i = 0; error2[i]; i += 1 )
alt_putchar( error2[i] );
alt_putchar( '\n' );
break; /* Ask for a new number */
}
if( ok )
{
if( i > 10 )
{
alt_putchar( '\n' );
for( i = 0; error4[i]; i += 1 )
alt_putchar( error4[i] );
alt_putchar( '\n' );
ok = 0;
break; /* Ask for a new number */
}
if( num >= 0 && num <= 255 )
return( num );
for( i = 0; error3[i]; i += 1 )
alt_putchar( error3[i] );
alt_putchar( '\n' );
ok = 0;
break; /* Ask for a new number */
}
}
}
return( 0 ); /* Dead code, or the compiler complains */
}
#include <sys/alt_stdio.h>
void put_q7( char ); /* prototype */
char prom[] = "Calculated FIR-value in Q7 (in hex-code): 0x";
char hexasc (char in) /* help function */
{
in = in & 0xf;
if (in <=9 ) return (in + 0x30);
if (in > 9 ) return (in - 0x0A + 0x41);
return (-1);
}
void put_q7( char inval)
{
int i; /* Loop counter */
for( i = 0; prom[i]; i += 1 )
alt_putchar( prom[i] );
alt_putchar (hexasc ((inval & 0xF0) >> 4));
alt_putchar (hexasc (inval & 0x0F));
alt_putchar ('\n');
}
Each point in the FIR filter result is just a weighted sum of values from the unfiltered data. You shouldn't need anything other than plain multiplication and addition if you have 8-bit input data and 32-bit arithmetic.
A quick visit to Wikipedia tells me that Q7 is essentially an 8-bit 2's complement integer, so if the target platform uses 2's complement, then simply describing the byte received as (signed char) will give it the correct numerical value when promoted to an int. If you premultiply the coefficients by a power of two, then the weighted sum will be multiplied by that same power of 2. Rounded division is then simply adding a half-adjust value followed by a signed right shift. With 16-bit fractions, the premultiplied constants are:
#define FBITS 16 /* number of fraction bits */
const int C0 = (( 299<<FBITS) + 5000) / 10000; /* (int)(0.0299*(1<<FBITS) + 0.5) */
const int C1 = ((4701<<FBITS) + 5000) / 10000; /* (int)(0.4701*(1<<FBITS) + 0.5) */
/* Ditto for C3 and C2 */
#define HALF (1 << (FBITS) >> 1) /* Half adjust for rounding = (int)(0.5 * (1<<FBITS)) */
The reason for that oddness it to get the significant bits you want without depending on any floating point rounding. Now, if:
signed char input[4];
...contain the 4 most recent input values, your output value is:
sum = c0*input[0] + c1*input[1] + c2*input[2] + c3*input[3];
output = (signed char)((sum + HALF) >> FBITS);
Since all of your coefficients are positive and sum to 1.0, there's no possibility of overflow.
There are a number of optimizations you can try after you get a simple version working. One possible minor glitch with other coefficients is for that rounding of the C0-C3 constants to produce values that don't exactly add up to 1<<FBITS. I tested and it doesn't happen with these values (you'd need the c0*(1<<LBITS) to have a fraction part of exactly 0.5; meaning that all the other scaled coefficients would also have 0.5 as their fraction parts. They'd all round up and the sum would be too large by 2. That could add a very small unintended gain to your filter.
That can't occur with the coefficients you gave.
Edit: I forgot. Both the integer part and fraction part are in the same 32-bit int during the sum calculation. With 8 bits of input(7+sign) and 16 bits of fraction, you can have up to 2^(32 - 16 - 8) = 2^8 = 256 points in the filter (at this point, you will obviously have an array of coefficients, and a multiply-add loop to compute the sum. Should the (input size) + (fraction bits) + log2(filter size) exceed 32, then you can try to expand the sum field to a C99 long long or int64_t value, if that's available, or write extended-precision add and shift logic if not. Extended precision in hardware is far better to use, when available.
I want to extract bits of a decimal number.
For example, 7 is binary 0111, and I want to get 0 1 1 1 all bits stored in bool. How can I do so?
OK, a loop is not a good option, can I do something else for this?
If you want the k-th bit of n, then do
(n & ( 1 << k )) >> k
Here we create a mask, apply the mask to n, and then right shift the masked value to get just the bit we want. We could write it out more fully as:
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
You can read more about bit-masking here.
Here is a program:
#include <stdio.h>
#include <stdlib.h>
int *get_bits(int n, int bitswanted){
int *bits = malloc(sizeof(int) * bitswanted);
int k;
for(k=0; k<bitswanted; k++){
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
bits[k] = thebit;
}
return bits;
}
int main(){
int n=7;
int bitswanted = 5;
int *bits = get_bits(n, bitswanted);
printf("%d = ", n);
int i;
for(i=bitswanted-1; i>=0;i--){
printf("%d ", bits[i]);
}
printf("\n");
}
As requested, I decided to extend my comment on forefinger's answer to a full-fledged answer. Although his answer is correct, it is needlessly complex. Furthermore all current answers use signed ints to represent the values. This is dangerous, as right-shifting of negative values is implementation-defined (i.e. not portable) and left-shifting can lead to undefined behavior (see this question).
By right-shifting the desired bit into the least significant bit position, masking can be done with 1. No need to compute a new mask value for each bit.
(n >> k) & 1
As a complete program, computing (and subsequently printing) an array of single bit values:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned
input = 0b0111u,
n_bits = 4u,
*bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
bit = 0;
for(bit = 0; bit < n_bits; ++bit)
bits[bit] = (input >> bit) & 1;
for(bit = n_bits; bit--;)
printf("%u", bits[bit]);
printf("\n");
free(bits);
}
Assuming that you want to calculate all bits as in this case, and not a specific one, the loop can be further changed to
for(bit = 0; bit < n_bits; ++bit, input >>= 1)
bits[bit] = input & 1;
This modifies input in place and thereby allows the use of a constant width, single-bit shift, which may be more efficient on some architectures.
Here's one way to do it—there are many others:
bool b[4];
int v = 7; // number to dissect
for (int j = 0; j < 4; ++j)
b [j] = 0 != (v & (1 << j));
It is hard to understand why use of a loop is not desired, but it is easy enough to unroll the loop:
bool b[4];
int v = 7; // number to dissect
b [0] = 0 != (v & (1 << 0));
b [1] = 0 != (v & (1 << 1));
b [2] = 0 != (v & (1 << 2));
b [3] = 0 != (v & (1 << 3));
Or evaluating constant expressions in the last four statements:
b [0] = 0 != (v & 1);
b [1] = 0 != (v & 2);
b [2] = 0 != (v & 4);
b [3] = 0 != (v & 8);
Here's a very simple way to do it;
int main()
{
int s=7,l=1;
vector <bool> v;
v.clear();
while (l <= 4)
{
v.push_back(s%2);
s /= 2;
l++;
}
for (l=(v.size()-1); l >= 0; l--)
{
cout<<v[l]<<" ";
}
return 0;
}
Using std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
#prateek thank you for your help. I rewrote the function with comments for use in a program. Increase 8 for more bits (up to 32 for an integer).
std::vector <bool> bits_from_int (int integer) // discern which bits of PLC codes are true
{
std::vector <bool> bool_bits;
// continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
for (int i = 0; i < 8; i++)
{
bool_bits.push_back (integer%2); // remainder of dividing by 2
integer /= 2; // integer equals itself divided by 2
}
return bool_bits;
}
#include <stdio.h>
int main(void)
{
int number = 7; /* signed */
int vbool[8 * sizeof(int)];
int i;
for (i = 0; i < 8 * sizeof(int); i++)
{
vbool[i] = number<<i < 0;
printf("%d", vbool[i]);
}
return 0;
}
If you don't want any loops, you'll have to write it out:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 7;
#if 0
bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
#else
#define BTB(v,i) ((v) & (1u << (i))) ? true : false
bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
#undef BTB
#endif
printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);
return 0;
}
As demonstrated here, this also works in an initializer.