Trouble printing decimal to binary number properly - c

I'm trying to write code to print the binary representation of a number. This was my attempt:
#include <stdio.h>
void getBinary(int num);
int main(void) {
int num = 2;
getBinary(num);
return 0;
}
void getBinary(int num) {
int mask = 1 << 31, i;
int temp;
for (i = 31; i >= 0; i--) {
temp = num & mask;
if (temp > 0)
printf("1");
else
printf("0");
mask = mask >> 1;
}
printf("\n");
}
And this doesn't work. If i make num = 2 my output will be ...0011. This is the answer I was given:
void getBinary(int);
int main()
{
int num=0;
printf("Enter an integer number :");
scanf("%d",&num);
printf("\nBinary value of %d is =",num);
getBinary(num);
return 0;
}
/*Function definition : getBinary()*/
void getBinary(int n)
{
int loop;
/*loop=15 , for 16 bits value, 15th bit to 0th bit*/
for(loop=15; loop>=0; loop--)
{
if( (1 << loop) & n)
printf("1");
else
printf("0");
}
}
and this will give the correct output. Why? What is different between my code and this. Aren't they doing the same thing with the solution doing it in fewer steps?

#include <stdio.h>
void getBinary(int num);
int main(void) {
unsigned int num = 2;
getBinary(num);
return 0;
}
void getBinary(int num) {
unsigned int mask = 1 << 31;
int i;
unsigned int temp;
for (i = 31; i >= 0; i--) {
temp = num & mask;
if (temp > 0)
printf("1");
else
printf("0");
mask = mask >> 1;
}
printf("\n");
}
For those curious, this is the correct answer. Just make the mask unsigned.

You have some problems in the code:
1 << 31 invokes undefined behavior because of signed arithmetic overflow. On your platform it most likely produces the value INT_MIN, that has the expected bit configuration but is negative.
temp > 0 might fail incorrectly if num < 0, because the sign bit will make temp negative too.
shifting mask to the right when its value is negative has an implementation defined result: On your platform it duplicates the sign bit, therefore mask will not have a single bit as expected, but all bits set above the current one. This explains the observed behavior.
You should use type unsigned int in function getBinary for num, temp and mask to get correct behavior.
Here is a corrected version of your code:
#include <stdio.h>
void getBinary(unsigned int num);
int main(void) {
unsigned int num = 2;
getBinary(num);
return 0;
}
void getBinary(unsigned int num) {
unsigned int mask = 1U << 31;
unsigned int temp;
for (int i = 31; i >= 0; i--) {
temp = num & mask;
if (temp != 0)
printf("1");
else
printf("0");
mask = mask >> 1;
}
printf("\n");
}
The proposed solution only prints 16 bits, which may or may not have been the specification. If the int type is larger than 16 bits, the bit shift will not overflow and everything is fine. If int has 16 bits, 1 << 15 invokes undefined behavior, so the solution is not strictly correct, but will function on most current platforms.
Here is a simpler solution:
void getBinary(unsigned int num) {
for (int shift = 32; shift-- > 0;) {
putchar('0' + ((num >> shift) & 1));
}
putchar("\n");
}
Initialize shift to 16 to print only the low order 16 bits.

Related

Converting decimal into binary in c using pointers

Write a function int* dec2bin(int N, int* n), which, given a natural number 0 ≤ N < 65535, computes and returns its representation in the binary numeral system. The program has to determine the coefficients ai ∈ {0,1}, i = 0,...,n − 1, such that N = (sum->n-1) ai2^i (n ≤ 16).
#include <stdio.h>
#include <math.h>
#include <assert.h>
int decimalToBinary(int N)
{
int B_Number = 0;
int c= 0;
int ctr=0;
while (N != 0) {
int rem = N % 2;
c = pow(10, ctr);
B_Number += rem * c;
N /= 2;
ctr++;
}
return B_Number;
}
int main()
{
int N;
scanf("%d", &N);
printf("%d", decimalToBinary(N));
return 0;
}
I know how to make a program that converts the numbers but I don't understand why the pointer is needed for and how to implement it.
Another way...
This was written to print the binary representation of a value (left-to-right). Instead of printing, you could simply assign the 0/1 (left-to-right) to a passed array (of 16 integers), then return the number of assigned integers to the calling function to print them from a loop.
int main() {
for( int i = 253; i <= 258; i++ ) {
printf( "Decimal %d: ", i );
unsigned int bitmask = 0;
bitmask = ~bitmask;
bitmask &= ~(bitmask >> 1); // High bitmask ready
// skip over leading 0's (optional)
while( bitmask && (bitmask & i) == 0 ) bitmask >>= 1;
// loop using bitmask to output 1/0, then shift mask
do {
putchar( (bitmask & i) ? '1' : '0' );
} while( (bitmask >>= 1) != 0 );
putchar( '\n' );
}
return 0;
}
Use an integer type capable of encoding the decimal number 1111_1111_1111_1111: use long long.
Do not use pow(), a floating point function for an integer problem. It may generate value just slightly smaller than the integer expected and is slow.
long long decimalToBinary_alt(int N) {
long long B_Number = 0;
long long power = 1;
while (N != 0) {
int rem = N % 2; // result: -1, 0, or 1
B_Number += rem * power;
N /= 2;
power *= 10; // Scale the power of 10 for the next iteration.
}
return B_Number;
}
Usage
printf("%lld\n", decimalToBinary(N));
Your function does not have the required parameters and return value.
int* dec2bin(int N, int* n)
{
unsigned uN = N;
for(int bit = 15; bit >= 0; bit--)
{
*(n + 15 - bit) = !!(uN & (1U << bit));
}
return n;
}

Converting from decimal to base 4 using bitmasking

I'm trying to write a program that converts from decimal to base 4 using bit masking. First I wrote this program that converts from decimal to binary to understand how it works
#include <stdio.h>
void binary(unsigned int num) {
int i;
unsigned temp, mask=1;
mask<<=31;
for(i=0; i<32; i++) {
temp=num&mask;
printf("%d", temp>>(31-i));
mask>>=1;
}
}
int main () {
int n;
printf("Enter a number:\n");
scanf("%d", &n);
binary(n);
return 0;
}
Then I was trying to use the same approach here
void base4(unsigned int num) {
int i;
unsigned temp, mask=3;
mask<<=15;
for(i=0; i<16; i++) {
temp= // <<<==== ???
printf("%d", temp>>(15-i)*2);
mask>>=1;
}
I know that in in base 4, numbers use 2 bits. So if we are ANDing each bit of a given value lets say 22 with the corresponding bit of the mask=3 we will end up with something like this
.... 0 0 1 1 2 (base4)
.... 00 00 01 01 10 (bin)
I just couldn't use this information to apply it to my previous approach, would be great if someone could help.
char *toBase4(char *buff, unsigned val, int printZeroes)
{
char *wrk = buff;
int shift = sizeof(val) * CHAR_BIT - 2;
unsigned mask = 3 << shift;
do
{
if((val & mask) || printZeroes)
{
*wrk++ = ((val & mask) >> shift) + '0';
printZeroes = 1;
}
mask >>= 2;
}while((shift -= 2) >= 0);
*wrk = 0;
return buff;
}
int main(void)
{
char x[256];
printf("%s\n", toBase4(x, 0xff00, 0));
printf("%s\n", toBase4(x, 0xff00, 1));
}
void base4(unsigned int num) {
int i;
unsigned int temp, mask=3;
mask<<=30;
for(i=0; i<16; i++) {
temp=num&mask;
printf("%d", temp>>(15-i)*2);
mask>>=2;
}
}

How to rotate bits to the left and add rotated bits to the right

I'm trying to get my program to work, where I shift bits to the left and add the shifted bits to the right. For example 00111000, if you shift it 4 positions to the left, the outcome should be 10000011. How can I make this work, I know that I need to use the bitwise OR. I have added the main function below.
#include <stdio.h>
#include <stdlib.h>
void printbits(int b){
int i;
int s = 8 * (sizeof b) - 1; /* 31 if int is 32 bits */
for(i=s;i>=0;i--)
putchar( b & 1<<i ? '1' : '0');
}
int main(){
char dir; /* L=left R=right */
int val, n, i;
scanf("%d %d %c",&val, &n, &dir);
printbits(val);putchar('\n');
for (i=0; i<10; i++){
if (dir=='L' || dir =='l')
rotateLeft(&val, n);
else
rotateRight(&val,n);
printbits(val); putchar('\n');
}
return;
}
This is the rotateLeft en rotateRight function.
#include <stdio.h>
#include <stdlib.h>
void rotateLeft(int *val, int N){
int num = val[0];
int pos = N;
int result = num << pos;
}
void rotateRight(int *val, int N){
int num = val[0];
int pos = N;
int result = num >> pos;
}
Here is a tested and non-optimized solution to complete your source code:
void rotateLeft(int *val, int N){
unsigned int num = val[0];
int pos = N;
unsigned int part1 = num << pos;
unsigned int part2 = (num >> ((sizeof(val[0])*CHAR_BIT)-pos));
if (N != 0) {
val[0] = part1 | part2;
}
}
void rotateRight(int *val, int N){
unsigned int num = val[0];
int pos = N;
unsigned int part1 = num >> pos;
unsigned int part2 = (num << ((sizeof(val[0])*CHAR_BIT)-pos));
if (N != 0) {
val[0] = part1 | part2;
}
}
To prevent automatic carry during the shift right, you have to
consider value as unsigned int.
To prevent N = 0 interference, assign the result to the entry only when (N != 0). (See remark on post ROL / ROR on variable using inline assembly in Objective-C)
MSB = (n >> (NUM_OF_BITS_IN_INT - 1))
n = (n << 1) | MSB;
Left bit rotation of n by 1 bit.
You are just shrugging off the MSB but not adding it back at LSB position.
use the functions in this link for performing the rotations:
https://en.wikipedia.org/wiki/Circular_shift

How to randomize lowest bits in a 64 bit pattern

I am interested in learning more about the concepts behind bit shifting and the manipulation of randomly generated bits. Below is some code that prints 20 random 64 bit patterns. "rand_bits" uses the C standard rand() to return a 64 bit pattern with all zeros except for the lowest bits, which are randomized. The number of low randomized bits is provided by the only parameter to the function.
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(64);
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;
}
/*
* Name: rand_bits
* Function: Returns a 64 bit pattern with all zeros except for the
* lowest requested bits, which are randomized.
* Parameter, "bit_cnt": How many of the lowest bits, including the
* lowest order bit (bit 0) to be randomized
* Return: A 64 bit pattern with the low bit_cnt bits randomized.
*/
uint64_t rand_bits(unsigned int bit_cnt) {
printf("int bit_cnt:", bit_cnt);
uint64_t result = rand();
uint64_t result_1 = result>>5;
// uint64_t result_1 = result>>7;
//return result;
return result_1;
}
For example, if the function is called with 24 as the argument value, it might return a
64 bit pattern, such as:
0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_​1101_0110_0101_1110_0111_1100
Currently the function rand_bits may show more than 15 random bits coming from the rand() function, but this is by NO means guaranteed.
I thought that to get the 40 bits like in the example I could right shift the bits, but that does not seem to be the concept. Does this require a bit mask of the higher order bits or a mod calculation on the random number generator?
Any suggestions of how to return a bit pattern of all zeros with its lowest bits (bit_cnt) randomized?
UPDATE:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
const int LINE_CNT = 20;
uint64_t rand_bits( unsigned number_of_bits ){
uint64_t r = 0;
unsigned i;
for(i = 0; i <= number_of_bits / 15; i++ ){
r = (r << 15) | (rand() & 0x7fff ) ;
}
return r & ~(~0ull << number_of_bits) ;
}
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;
}
int main(void) {
int i;
/* for(i = 0; i < 64; i++)
print_bin(rand_bits(i),64);
return EXIT_SUCCESS;
*/
//I want to keep the code like this, but have the output shown in //the links.
srand(time(NULL));
for(i = 0; i < LINE_CNT; i++) {
uint64_t val64 = rand_bits(64);
print_bin(val64, 64);
}
return EXIT_SUCCESS;
}
When I keep the code in main the way I had it originally, the output is all 0s. Any suggestions of how I can keep my code the way it was in main originally and produce exactly 20 lines of 64 bits with the lowest bits randomized?
rand() generates an int in the range [0 ...RAND_MAX]. RAND_MAX is at least 32767 and certainly is 1 less than a power of 2.
So efficiently loop a few times until we have bit_cnt random bits. This trick is to minimize the loop count by taking advantage that RAND_MAX is likely greater than 32767.
#include <stdlib.h>
// Valid for 0 <= bit_cnt <= uintmax_t bit wdith
uintmax_t randomized_lowest_bits(unsigned bit_cnt) {
// Create mask, same as maximum return value
uintmax_t mask = 1;
if (bit_cnt >= CHAR_BIT * sizeof(uintmax_t)) {
mask = -1;
} else {
mask = (mask << bit_cnt) - 1;
}
uintmax_t limit = mask;
uintmax_t x = 0;
while (limit) {
// x *= (RAND_MAX +1)
// Done as below to prevent numeric overflow of `RAND_MAX + 1u` on rare machines.
// Let the compiler optimize it, likely into a fixed count left shift
#if RAND_MAX == INT_MAX
x = x * (RAND_MAX / 2 + 1) * 2;
#else
x *= RAND_MAX + 1;
#endif
// Bring in more bits
x += rand();
// Carefully divide by RAND_MAX + 1 with overflow safe guards
// Again, let the compiler optimize the code, likely into a fixed count right shift
#if RAND_MAX == INT_MAX
limit = (limit / (RAND_MAX / 2 + 1)) / 2;
#else
limit /= RAND_MAX + 1;
#endif
}
return x & mask;
}
void testR(void) {
for (int i = 0; i <= 64; i++) {
printf("%jX\n", randomized_lowest_bits(i));
}
}
Output
0
1
3
...
1192962917E96171
24833D39561F3B29
C3EC4ED846755A5B
uint64_t rand_bits(unsigned int number_of_bits)
{
uint64_t r = 0;
int i;
for(i = 0 ; i < number_of_bits/15 ; i++ )
{
r = (r<<15)|(rand()&32767u);
}
int remainder = number_of_bits-i*15;
r = (r<<remainder)|(rand()&~(~0ull<<remainder));
return r;
}
Since RAND_MAX is guaranteed to provide 15 bits, there's no point doing 1 bit a time.
By concatenating a sufficient number of 15 bit random sequences, then masking the unwanted bits when number_of_bits is not an exact multiple of 15:
uint64_t rand_bits( int number_of_bits )
{
uint64_t r = 0;
for( int i = 0; i <= number_of_bits / 15; i++ )
{
r = (r << 15) | (rand() & 0x7fff ) ;
}
return r & ((number_of_bits >= 64) ? ~0ull :
~(~0ull << number_of_bits) ) ;
}

Reading/Writing bits in memory

Let's say I'm given a void* memory address and I need to print the bits located in this memory address. How can I do this?
In my processor memory addresses are 32bits as are memory values, also int are 32 bits.
So I thought of doing this:
unsigned int value = *memory_address;
and then by simple arithmetic (some mod and div operations) to get the bits of the value saved in memory_address.
For example value mod 2 will give last bit of this value and so on. But from what I can tell (I was expecting different bits) it doesn't work. Any ideas why?
Also, is anyone aware of ready C source code that "does" such this, reads/writes bits from memory?
Shift the value by one for each bit and or it with 1
unsigned int value = *((unsigned int*)memory_address);
for( int i = 0; i < 32; i++)
{
printf("%d ", value >> i & 1);
}
You can also do it with math operators. You have to get the bit value (2 to the power of the bit index) and substract that value at each iteration to make sure the modulo doesn't return values that we seen before:
for( int i = 0; i < 32; i++)
{
int bit_value = (int)pow(2,i + 1);
int num_bit_value = value % bit_value;
printf("%d ", num_bit_value ? 1 : 0 );
value -= num_bit_value;
}
int main() {
int a = 0xFFFF;
void * v = &a; // v points to a
int * aPtr = (int *) v; // aPtr also points to a
int b = *aPtr; // b gets the value aPtr points to, aka a or 0xFFFF
int aBit = (b >> 3) & 1; // aBit now contains bit 3 of the original a value
// toggle the bit
if (aBit) {
b &= ~(1 << 3); // set bit 3 to 0
} else {
b |= (1 << 3); // set bit 3 to 1
}
*aPtr = b; // update original a
}
I found it easier to think of the memory as a continuous string of characters rather than a void pointer. This way you can address as many bits as you want.
Here is how I have done it.
unsigned char
get_bit(char *array, int bit)
{
int byte, k;
byte = bit/8;
k = 7 - bit % 8;
return array[byte] & (1 << k);
}
void
set_bit(char *array, int bit, unsigned char value)
{
int byte, k;
byte = bit/8;
k = 7 - bit % 8;
if (value)
array[byte] |= (1 << k);
else
array[byte] &= ~(1 << k);
}
How about:
bool isBit4Set = ((*someAddress) & 0x8 != 0);
(*someAddress) |= 0x8; // Set bit 4
Generic solution for printing bytes and bits.
void dump_data(const void *object, size_t size)
{
int i;
printf("[ \n");
for(i = 0; i < size; i++)
{
if (i%4 ==0)
{
printf("#%02X",&((const unsigned char *) object)[i]);
printf("[ ");
}
printf("%02x ", ((const unsigned char *) object)[i] & 0xff);
if ((i+1)%4 == 0)
printf("]\n");
}
printf("]\n");
printf("BINARY FORMAT\n");
for (i = 0; i < size; i++)
{
printf("#%02X",&((const unsigned char *) object)[i]);
printf("[ ");
unsigned char value = (((unsigned char*)object)[i]);
for(int j=0; j<8; j++)
printf("%d ", (value & (0x80 >> j)) ? 1 : 0); // right shifting the value will print bits in reverse.
printf("]\n");
}
}
bool getBit(void* data,int bit){ return ((*((int*)data)) & 1<<bit); }
void setBit(void* data,int bit,bool set){ if(set){ (*((int*)data)) |= 1<<bit; }else{ (*((int*)data)) &= ~(1<<bit); } }
for simple usage

Resources