As part of an exercise, I have to rewrite a recursive function so that the new function is not recursive. Both functions need to convert positive decimal integer inputs into their binary equivalent.
This is the code using recursion:
void convert(int n) { //recursive
if (n > 0) {
convert(n/2);
printf("%d", n%2);
}
return;
}
Here's my code:
void convert(int n) { //non-recursive
while (n > 0) {
printf("%d", n%2);
n/=2;
}
return;
}
The problem with my code is that, understandably, my binary conversion gets printed out backwards. For example, if I enter the number 8, my function returns 0001, if I enter 2, 01 is returned, etc.
Any suggestions for a quick fix using only the stdio.h library?
Here's a non-recursive version that produces the same result as your recursive version and doesn't require an array:
void convert(int n) {
int s;
for (s = 1; n/s/2 > 0; s *= 2)
;
for (; s >= 1; s /= 2) {
printf("%d", (n/s) % 2);
}
}
This version handles zero and large numbers (but not negative numbers).
You can do this in one loop:
if(num == 0) {
printf("0\n"); // Check for num being 0.
return;
}
num = num < 0 ? num*-1 : num; // Make sure the number has no sign bit.
char first1Found = 0; // Create a check for the first 1 printed.
for (int i = sizeof(num)*8 - 1; i >= 0 ; --i) {
if (num & (1 << i)) { // If its a 1, print it and set the first1Found bool.
printf("1");
first1Found = 1;
} else if(first1Found) { // If its a 0 only print it if its not a leading 0.
printf("0");
}
}
printf("\n");
Here is a live example.
Note: I have used 8 by making an assumption that sizeof returns bytes in a type. This may not be true of all systems and compilers (although should be). A more portable way might be to use CHAR_BIT from <limits.h> as suggested by #chux.
Here's a variant that's explicit about using bit-masking and shifting the location of the mask from the upper end downwards. It behaves like your recursive version, in that it doesn't do negatives or zero.
void convert(int n) {
for(int mask = 1 << (8 * sizeof(n) - 2); mask > 0; mask >>= 1) {
if (mask <= n) {
putchar((n & mask) ? '1' : '0');
}
}
putchar('\n');
}
C99 variation on #Tom Karzes fine answer that handles all + and - values including INT_MIN.
void convertm(int n) {
if (n < 0) {
putchar('-');
} else {
n = -n;
}
// Build up a negative power-of-2 that meets/exceeds `n`
int npow2;
for (npow2 = -1; n/2 <= npow2 ; npow2 *= 2)
;
// For each negative power-of-2 ...
while (npow2) {
putchar(n / npow2 + '0');
n %= npow2;
npow2 /= 2;
}
puts("");
}
A reliable way to print an unpadded binary representation of an unsigned valued (any size capable of fitting within a long unsigned) is:
/** unpadded binary representation of 'v'. */
void binprn (const unsigned long v)
{
if (!v) { putchar ('0'); return; };
size_t sz = sizeof v * CHAR_BIT;
unsigned long rem = 0;
while (sz--)
if ((rem = v >> sz))
putchar ((rem & 1) ? '1' : '0');
}
(CHAR_BIT (usually 8) is provided in limits.h). You do not "need" to use limits.h -- that's just where it CHAR_BIT is normally found. All you need is a constant, you can call it anything you like. I generally just use:
/* CHAR_BIT */
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
Related
Here is a sample code
int x = rand() % 90000;
When I was doing something like this I realized all the numbers were around 0 - 30000.
Is there a limit for this? If there is how can I use it without limits?
You should not use rand(), because it is quite poor in many C standard library implementations. It will return a pseudorandom number between 0 and RAND_MAX, inclusive, but RAND_MAX is often relatively small; for example, 32767.
Using the modulo operator to yield a range of integers is problematic if the range is a large fraction of the range of values the generator function can return, because the distribution is not exactly uniform.
For example, let's say RAND_MAX is 59999, and we used rand() % 40000. The probability of the result being between 0 and 19999 is 67%, but only 33% between 20000 and 39999. This is because that rand() produces a value in [0,19999] at 1/3 probability, [20000,39999] at 1/3 probability, and [40000..59999] at 1/3 probability; but that last third folds back so that it yields [0,19999] after the modulo operation!
For small ranges the bias is not so noticeable.
Personally, I like to generate enough random bits to cover the desired range, then use the exclusion method to pick the value.
If we need to use rand(), we can use the following helper function to generate a pseudorandom number whose range is at least atleast (but may be larger; i.e. it can return a larger value):
#include <inttypes.h>
static inline uint64_t rand_atleast(uint64_t atleast)
{
uint64_t result = 0;
do {
result = ((uint64_t)RAND_MAX + 1) * result + (uint64_t)rand();
atleast /= ((uint64_t)RAND_MAX + 1);
} while (atleast > 0);
return result;
}
To use the exclusion method to create ints within a desired range, we can use a structure to contain the stuff we need, a helper function to initialize that range (to describe some specific range of ints), and another helper function to generate integers within that range:
struct range_spec {
uint64_t mask;
uint64_t limit;
int base;
};
static inline void set_range(struct range_spec *spec,
int minimum, int maximum)
{
uint64_t mask;
int base;
if (minimum <= maximum) {
base = minimum;
mask = maximum - minimum;
} else {
base = maximum;
mask = minimum - maximum;
}
spec->base = base;
spec->limit = mask;
mask |= mask >> 1;
mask |= mask >> 2;
mask |= mask >> 4;
mask |= mask >> 8;
mask |= mask >> 16;
mask |= mask >> 32;
spec->mask = mask;
}
static inline int rand_range(const struct range_spec *spec)
{
const uint64_t mask = spec->mask;
const uint64_t limit = spec->limit;
uint64_t result;
do {
result = rand_atleast(mask) & mask;
} while (result > limit);
return spec->base + result;
}
However, this is a lot of work to get pretty poor pseudorandom numbers: not worth it in my opinion.
I usually use Xorshift64* instead. It is fast, quite random (see this extended comment of mine), and really easy to implement.
Essentially, you can use a small header file, say rng64.h:
#ifndef RNG64_H
#define RNG64_H
#include <inttypes.h>
#include <time.h>
typedef struct {
uint64_t limit;
int64_t base;
int shift;
} rng64_intrange_spec;
static uint64_t rng64_state = 1;
static inline uint64_t rng64(void)
{
uint64_t x = rng64_state;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
rng64_state = x;
return x * UINT64_C(2685821657736338717);
}
static inline uint64_t rng64_randomize(void)
{
uint64_t x;
int n = 1000;
x = ((uint64_t)time(NULL) * UINT64_C(19076794157513))
^ ((uint64_t)clock() * UINT64_C(809712647));
if (!x)
x = 1;
while (n-->0) {
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
}
rng64_state = x;
return x;
}
static inline double rng64_one(void)
{
return (double)rng64() / 18446744073709551616.0;
}
static inline int64_t rng64_intrange(rng64_intrange_spec *spec)
{
const uint64_t limit = spec->limit;
const int shift = spec->shift;
uint64_t value;
do {
value = rng64() >> shift;
} while (value > limit);
return spec->base + value;
}
static inline void rng64_set_intrange(rng64_intrange_spec *spec,
int64_t minimum,
int64_t maximum)
{
int64_t base;
uint64_t limit;
int bits = 0;
if (minimum <= maximum) {
base = minimum;
limit = maximum - minimum;
} else {
base = maximum;
limit = minimum - maximum;
}
spec->base = base;
spec->limit = limit;
while (limit >= 32768) {
limit >>= 16;
bits += 16;
}
while (limit >= 8) {
limit >>= 4;
bits += 4;
}
while (limit > 0) {
limit >>= 1;
bits += 1;
}
spec->shift = 64 - bits;
}
#endif /* RNG64_H */
Somewhere near the beginning of your program, call rng64_randomize() to generate a state based on the current time (wall clock via time(), and CPU time used to execute the current process via clock()). The initial state is churned a bit, to ensure you don't get similar sequences when running the code in quick succession. You can set the rng64_state to any value except zero, to generate a specific sequence. (Zero state will generate only zeroes.) I recommend using
printf("Using %" PRIu64 " as the Xorshift64* random number seed.\n", rng64_randomize());
which prints both the seed, and the pseudorandom number generator algorithm used, near the beginning of the program. That allows someone to reproduce the test (by setting rng64_state to that value instead of calling rng64_randomize(), or reimplement the test using their own equivalent code). Reproducibility is good.
While (uint64_t)time(NULL) is not guaranteed to work by the C standard, it does work in all current widely-used C implementations I am aware of.
If you want to compare to a different pseudorandom number generator, just reimplement another using a similar header file, and include that instead. That way you don't need to change any code that uses the generator, only the generator code itself.
rng_one() returns uniform pseudorandom numbers between 0 and 1.0, inclusive. If you want the upper limit to be exclusive, use e.g.
static inline double rng64_one(void)
{
double r;
do {
r = (double)rng64() / 18446744073709551616.0;
} while (r >= 1.0);
return r;
}
and if both limits exclusive (so it never returns 0.0 or 1.0 exactly), while (r <= 0.0 || r >= 1.0); instead.
Here's an example of how to use the rng64.h above:
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include "rng64.h"
int main(int argc, char *argv[])
{
rng64_intrange_spec r;
int minval, maxval, count, i;
char dummy;
if (argc != 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s MIN MAX COUNT\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This program outputs COUNT pseudorandom integers,\n");
fprintf(stderr, "between MIN and MAX, inclusive.\n");
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
if (sscanf(argv[1], " %d %c", &minval, &dummy) != 1) {
fprintf(stderr, "%s: Invalid minimum.\n", argv[1]);
return EXIT_FAILURE;
}
if (sscanf(argv[2], " %d %c", &maxval, &dummy) != 1 || maxval < minval) {
fprintf(stderr, "%s: Invalid maximum.\n", argv[2]);
return EXIT_FAILURE;
}
if (sscanf(argv[3], " %d %c", &count, &dummy) != 1 || count < 0) {
fprintf(stderr, "%s: Invalid count.\n", argv[3]);
return EXIT_FAILURE;
}
fprintf(stderr, "Generating %d pseudorandom integers in [%d, %d],\n", count, minval, maxval);
fprintf(stderr, "using Xorshift64* with seed %" PRIu64 ".\n", rng64_randomize());
fflush(stderr);
rng64_set_intrange(&r, minval, maxval);
for (i = 0; i < count; i++)
printf("%d\n", (int)rng64_intrange(&r));
return EXIT_SUCCESS;
}
Specify the minimum and maximum values (integers), and the number of integers to output, as command-line parameters.
We all know sgn() function. It can be implemented in C like something along these lines:
inline int sgn(int x)
{
if(x > 0) {
return 1;
} else if(x < 0) {
return -1;
} else {
return 0;
}
}
Or, a more efficient, branchless version:
inline int sgn(int x)
{
return (x > 0) - (x < 0);
}
What I want to know is the fastest method of computing the opposite of the sign of a given number, which can be written like this:
inline int asgn(int x)
{
if(x > 0) {
return -1;
} else if(x < 0) {
return 1;
} else {
return 0;
}
}
The fastest way to do this that I know of:
inline int asgn(int x)
{
return (x >> (sizeof(x) * CHAR_BIT - 1)) | !!x;
}
The only flow of this approach is that it relies on the right bit shift of signed numbers being arithmetic, which, according to the standard, doesn't have to be the case. Is there a faster and/or more portable solution?
Couldn't you just switch the order of
inline int sgn(int x)
{
return (x > 0) - (x < 0);
}
to
inline int asgn(int x)
{
return (x < 0) - (x > 0);
}
By the way, unless your input data is fairly random, the branchless code might be slower than the "branchy" code due to branch prediction. Best to try out both versions and see which is actually faster for you.
Convert to an unsigned int. That's well defined, if a bit counter-intuitive. Then you can access top bit without any arithmetical problems.
Two's complement is not guaranteed, but the chance of having a one's complement machine is so low it's probably not worth worrying about.
Get rid of the shift on signed numbers. Indeed you cannot assume that there will be an arithmetic right-shift, while shifts on unsigned numbers are always well-defined. Something like this should be both branch-free and portable:
#include <limits.h>
#include <stdio.h>
int sgn(int x)
{
unsigned int msb = (unsigned int)x & (1u << (sizeof(int)*CHAR_BIT-1));
return !!x - 2*!!(int)msb;
}
int asgn(int x)
{
unsigned int msb = (unsigned int)x & (1u << (sizeof(int)*CHAR_BIT-1));
return 2*!!(int)msb - !!x;
}
int main(void)
{
printf("%d\t%d\n", sgn(-5), asgn(-5));
printf("%d\t%d\n", sgn( 5), asgn( 5));
printf("%d\t%d\n", sgn( 0), asgn( 0));
return 0;
}
Output:
-1 1
1 -1
0 0
msb in this case is used as "a kind of boolean" to indicate if a number is signed or not.
#include <stdio.h>
int NumberOfSetBits(int);
int main(int argc, char *argv[]) {
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
int n = 3;
int count = NumberOfSetBits(n);
printf("Number of set bits is: %d\n", count);
printf("Number of unset bits is: %d", total_bit_size - count);
}
int NumberOfSetBits(int x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x = x >> 1;
}
return count;
}
Number of set bits is: 2
Number of unset bits is: 30
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
^ that will get the size of the int on the system and times it by 8 which is the number of bits in each byte
EDITED: Without the use of the ~
/*
Calculate how many set bits and unset bits are in a binary number aka how many 1s and 0s in a binary number
*/
#include <stdio.h>
unsigned int NumberOfSetBits(unsigned int);
unsigned int NumberOfUnSetBits(unsigned int x);
int main() {
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
unsigned int n = 3;
printf("Number of set bits is: %u\n", NumberOfSetBits(n));
printf("Number of unset bits is: %u", NumberOfUnSetBits(n));
return 0;
}
unsigned int NumberOfSetBits(unsigned int x) {
// counts the number of 1s
unsigned int count = 0;
while (x != 0) {
count += (x & 1);
// moves to the next bit
x = x >> 1;
}
return count;
}
unsigned int NumberOfUnSetBits(unsigned int x) {
// counts the number of 0s
unsigned int count = 0;
while(x != 0) {
if ((x & 1) == 0) {
count++;
}
// moves to the next bit
x = x >> 1;
}
return count;
}
returns for input 3
Number of set bits is: 2
Number of unset bits is: 0
unset bits is 0? Doesn't seem right?
if I use NumberOfSetBits(~n) it returns 30
You've got a problem on some systems because you right shift a signed integer in your bit-counting function, which may shift 1's into the MSB each time for negative integers.
Use unsigned int (or just unsigned) instead:
int NumberOfSetBits(unsigned x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x >>= 1;
}
return count;
}
If you fix that part of the problem, you can solve the other with:
int nbits = NumberOfSetBits(~n);
where ~ bitwise inverts the value in n, and hence the 'set bit count' counts the bits that were zeros.
There are also faster algorithms for counting the number of bits set: see Bit Twiddling Hacks.
To solve the NumberOfSetBits(int x) version without assuming 2's complement nor absence of padding bits is a challenge.
#Jonathan Leffler has the right approach: use unsigned. - Just thought I'd try a generic int one.
The x > 0, OP's code work fine
int NumberOfSetBits_Positive(int x) {
int count = 0;
while (x != 0) {
count += (x & 1);
x = x >> 1;
}
return count;
}
Use the following to find the bit width and not count padding bits.
BitWidth = NumberOfSetBits_Positive(INT_MAX) + 1;
With this, the count of 0 or 1 bits is trivial.
int NumberOfClearBits(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits(x);
}
int NumberOfSetBits_Negative(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
All that is left is to find the number of bits set when x is 0. +0 is easy, the answer is 0, but -0 (1's compliment or sign magnitude) is BitWidth or 1.
int NumberOfSetBits(int x) {
if (x > 0) return NumberOfSetBits_Positive(x);
if (x < 0) return NumberOfSetBits_Negative(x);
// Code's assumption: Only 1 or 2 forms of 0.
/// There may be more because of padding.
int zero = 0;
// is x has same bit pattern as +0
if (memcmp(&x, &zero, sizeof x) == 0) return 0;
// Assume -0
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
here is a proper way to count the number of zeores in a binary number
#include <stdio.h>
unsigned int binaryCount(unsigned int x)
{
unsigned int nb=0; // will count the number of zeores
if(x==0) //for the case zero we need to return 1
return 1;
while(x!=0)
{
if ((x & 1) == 0) // the condition for getting the most right bit in the number
{
nb++;
}
x=x>>1; // move to the next bit
}
return nb;
}
int main(int argc, char *argv[])
{
int x;
printf("input the number x:");
scanf("%d",&x);
printf("the number of 0 in the binary number of %d is %u \n",x,binaryCount(x));
return 0;
}
I have the following function that sets the N highest bits, e.g. set_n_high(8) == 0xff00000000000000
uint64_t set_n_high(int n)
{
uint64_t v = 0;
int i;
for (i = 63 ; i > 63 - n; i--) {
v |= (1llu << i);
}
return v;
}
Now just out of curiosity, is there any way in C to accomplish the same without using a loop (or a lookup table) ?
EDIT: n = 0 and n = 64 are cases to be handled, just as the loop variant does.
If you're OK with the n = 0 case not working, you can simplify it to
uint64_t set_n_high(int n)
{
return ~UINT64_C(0) << (64 - n);
}
If, in addition to that, you're OK with "weird shift counts" (undefined behaviour, but Works On My Machine), you can simplify that even further to
uint64_t set_n_high(int n)
{
return ~UINT64_C(0) << -n;
}
If you're OK with the n = 64 case not working, you can simplify it to
uint64_t set_n_high(int n)
{
return ~(~UINT64_C(0) >> n);
}
If using this means that you have to validate n, it won't be faster. Otherwise, it might be.
If you're not OK with either case not working, it gets trickier. Here's a suggestion (there may be a better way)
uint64_t set_n_high(int n)
{
return ~(~UINT64_C(0) >> (n & 63)) | -(uint64_t)(n >> 6);
}
Note that negating an unsigned number is perfectly well-defined.
uint64_t set_n_high(int n) {
return ((1llu << n) - 1) << (64-n);
}
Use a conditional to handle n == 0 and then it becomes trivial.
uint64_t set_n_high(int n) {
/* optional error checking:
if (n < 0 || n > 64) do something */
if (n == 0) return 0;
return -(uint64_t)1 << 64 - n;
}
There’s really no good reason to do anything more complicated than that. The cast from int to uint64_t is fully specified, as are the negation and shift (because the shift amount is guaranteed to lie in [0,63] if n is in [0,64]).
well taking #harold's answer and changing it a little:
uint64_t set_n_high(int n)
{
int carry = n>>6;
return ~((~0uLL >> (n-carry)) >> carry);
}
For what it's worth, of the posts so far (that handle n of 0-64), this one produces the least amount of assembly on an x86_64 and a raspberry pi (and does 1 branch operation) (with gcc 4.8.2). It looks fairly readable too.
uint64_t set_n_high2(int n)
{
uint64_t v = 0;
if (n != 0) {
v = ~UINT64_C(0) << (64 - n);
}
return v;
}
Well I'm presenting a weird-looking one.
:)
/* works for 0<=n<=64 */
uint64_t set_n_high(int n)
{
return ~0llu << ((64 - n) / 4) << ((64 - n) * 3 / 4);
}
I wrote this function to remove the most significant bit in every byte. But this function doesn't seem to be working the way I wanted it to be.
The output file size is always '0', I don't understand why nothing's been written to the output file. Is there a better and simple way to remove the most significant bit in every byte??
In relation to shift operators, section 6.5.7 of the C standard says:
If the value of the right operand is negative or is greater than or
equal to the width of the promoted left operand, the behavior is
undefined.
So firstly, remove nBuffer << 8;. Even if it were well defined, it wouldn't be an assignment operator.
As people have mentioned, you'd be better off using CHAR_BIT than 8. I'm pretty sure, instead of 0x7f you mean UCHAR_MAX >> 1 and instead of 7 you meant CHAR_BIT - 1.
Let's just focus on nBuffer and bit_count, here. I shall comment out anything that doesn't use either of these.
bit_count += 7;
if (bit_count == 7*8)
{
*out_buf++ = nBuffer;
/*if((write(out_fd, bit_buf, sizeof(char))) == -1)
oops("Cannot write on the file", "");*/
nBuffer << 8;
bit_count -= 8;
}
nBuffer = 0;
bit_count = 0;
At the end of this code, what is the value of nBuffer? What about bit_count? What impact would that have on your second loop? while (bit_count > 0)
Now let's focus on the commented out code:
if((write(out_fd, bit_buf, sizeof(char))) == -1)
oops("Cannot write on the file", "");
Where are you assigning a value to bit_buf? Using an uninitialised variable is undefined behaviour.
Instead of going through all of the bits to find the high one, this goes through only the 1 bits. high() returns the high bit of the argument, or zero if the argument is zero.
inline int high(int n)
{
int k;
do {
k = n ^ (n - 1);
n &= ~k;
} while (n);
return (k + 1) >> 1;
}
inline int drop_high(int n)
{
return n ^ high(n);
}
unsigned char remove_most_significant_bit(unsigned char b)
{
int bit;
for(bit = 0; bit < 8; bit++)
{
unsigned char mask = (0x80 >> bit);
if( mask & b) return b & ~mask;
}
return b;
}
void remove_most_significant_bit_from_buffer(unsigned char* b, int length)
{
int i;
for(i=0; i<length;i++)
{
b[i] = remove_most_significant_bit(b[i]);
}
}
void test_it()
{
unsigned char data[8];
int i;
for(i = 0; i < 8; i++)
{
data[i] = (1 << i) + i;
}
for(i = 0; i < 8; i++)
{
printf("%d\r\n", data[i]);
}
remove_most_significant_bit_from_buffer(data, 8);
for(i = 0; i < 8; i++)
{
printf("%d\r\n", data[i]);
}
}
I won't go through your entire answer to provide your reworked code, but removing the most significant bit is easy. This comes from the fact that the most significant bit can easily be found by using log base 2 converted to an integer.
#include <stdio.h>
#include <math.h>
int RemoveMSB(int a)
{
return a ^ (1 << (int)log2(a));
}
int main(int argc, char const *argv[])
{
int a = 4387;
printf("MSB of %d is %d\n", a, (int)log2(a));
a = RemoveMSB(a);
printf("MSB of %d is %d\n", a, (int)log2(a));
return 0;
}
Output:
MSB of 4387 is 12
MSB of 291 is 8
As such, 4387 in binary is 1000100100011 with a most significant bit at 12.
Likewise, 291 in binary is 0000100100011 with a most significant bit at 8.