Convert int to binary string of certain size - c

I'm struggling to adapt to C after programming in Java for some time and I need help. What I'm looking for is a method that takes following input:
Integer n, the one to be converted to binary string (character array).
Integer length, which defines the length of the string (positions from the left not filled with the binary numbers are going to be set to default 0).
//Here's some quick code in Java to get a better understanding of what I'm looking for:
public static String convertToBinary(int length, int n) {
return String.format("%1$" + bit + "s", Integer.toBinaryString(value)).replace(' ', '0');
}
System.out.println(convertToBinary(8,1));
// OUTPUT:
00000001 (not just 1 or 01)
Any hints on what the equivalent of this would be in C? Also, could you provide me with an example of how the resulting binary string should be returned?
(not a duplicate, since what I'm looking for is '00000001', not simply '1')

The C standard library does not contain an equivalent function to Integer.toBinaryString(). The good news is, writing such a function won't be too complicated, and if you're in the process of learning C, this problem is fairly ideal for learning how to use the bitwise operators.
You'll want to consult an existing tutorial or manual for all the details, but here are a few examples of the sort of things that would be useful for this or similar tasks. All numbers are unsigned integers in these examples.
n >> m shifts all bits in n right by m steps, and fills in zeros on the left side. So if n = 13 (1101 in binary), n >> 1 would be 6 (i.e. 110), and n >> 2 would be 3 (i.e. 11).
n << m does the same thing, but shifting left. 3 << 2 == 12. This is equivalent to multiplying n by 2 to the power of m. (If it isn't obvious why that is, you'll want to think about how binary numbers are represented for awhile until you understand it clearly; it'll make things easier if you have an intuitive understanding of that property.)
n & m evaluates to a number such that each bit of the result is 1 if and only if it's 1 in both n and m. e.g. 12 & 5 == 4, (1100, 0101, and 0100 being the respective representations of 12, 5, and 4).
So putting those together, n & (1 << i) will be nonzero if and only if bit i is set: 1 obviously only has a single bit set, 1 << i moves it to the appropriate position, and n & (1 << i) checks if that position also has a 1 bit for n. (keeping in mind that the rightmost/least significant bit is bit 0, not bit 1.) So using that, it's a simple matter of checking each bit individually to see if it's 1 or 0, and you have your binary conversion function.

like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
char *convertToBinary(int length, int n) {
unsigned num = (unsigned)n;
int n_bit = CHAR_BIT * sizeof(num);
if(length > n_bit){
fprintf(stderr, "specified length greater than maximum length.\n");
length = n_bit;//or expand size?
}
char *bin = malloc(n_bit + 1);//static char bin[CHAR_BIT * sizeof(num)+1]; If you change, memmove(-->return p;), free is not necessary.
memset(bin, '0', n_bit);
bin[n_bit] = 0;
char *p = bin + n_bit;
do {
*--p = "01"[num & 1];
num >>= 1;
}while(num);
int bits = bin + n_bit - p;
if(bits < length){
p -= length - bits;
return memmove(bin, p, length + 1);
} else if(bits > length){
fprintf(stderr, "Specified length is not enough.(%s but length is %d)\n", p, length);
return memmove(bin, p, bits+1);//or cut off
/*
free(bin);
return ""; or return NULL;
*/
}// else if(bits == length)
return bin;
}
int main(void){
char *sbin = convertToBinary(8, 1);
puts(sbin);
free(sbin);
return 0;
}

Related

Function for binary conversion

I am trying to convert a decimal value to binary using the function I wrote in C below. I cannot figure out the reason why it is printing 32 zeroes rather than the binary value of 2.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
int binaryConversion(int num){
int bin_buffer[32];
int mask = INT_MIN;
for(int i = 0; i < 32; i++){
if(num & mask){
bin_buffer[i] = 1;
mask >> 1;
}
else{
bin_buffer[i] = 0;
mask >> 1;
}
}
for(int j = 0; j < 32; j++){
printf("%d", bin_buffer[j]);
}
}
int main(){
binaryConversion(2);
}
Thanks
Two mistakes:
You use >> instead of >>=, so you're not actually ever changing mask.
You didn't declare mask as unsigned, so when you shift, it'll get sign-extended, which you don't want.
If you put a:
printf("%d %d\n", num, mask);
immediately inside your for loop, you'll see why:
2 -2147483648
2 -2147483648
2 -2147483648
2 -2147483648
:
2 -2147483648
The expression mask >> 1 does right shift the value of mask but doesn't actually assign it back to mask. I think you meant to use:
mask >>= 1;
On top of that (once you fix that problem), you'll see that the values in the mask are a bit strange because right-shifting a negative value can preserve the sign, meaning you will end up with multiple bits set.
You'd be better off using unsigned integers since the >> operator will act on them more in line with your expectations.
Additionally, there's little point in writing all those bits into a buffer just so you can print them out later. Unless you need to do some manipulation on the bits (and this appears to not be the case here), you can just output them directly as they're calculated (and get rid of the now unnecessary i variable).
So, taking all those points into account, you can greatly simplify your code such as with the following complete program:
#include <stdio.h>
#include <limits.h>
int binaryConversion(unsigned num) {
for (unsigned mask = (unsigned)INT_MIN; mask != 0; mask >>= 1)
putchar((num & mask) ? '1' : '0');
}
int main(void) {
binaryConversion(2);
putchar('\n');
}
And just one more note, the value of INT_MIN is not actually required to just have the top bit set. Because of the current allowance by C to handle ones' complement and sign-magnitude (as well as two's complement) for negative numbers, it possible for INT_MIN to have a value with multiple bits set (such as -32767).
There are moves afoot to remove these little-used encodings from C (C++20 has already flagged this) but, for maximum portability, you could opt instead for the following function:
int binaryConversion(unsigned int num) {
// Done once to set topBit.
static unsigned topBit = 0;
if (topBit == 0) {
topBit = 1;
while (topBit << 1 != 0) topBit <<= 1;
}
// Loop to process all bits.
for (unsigned mask = topBit; mask != 0; mask >>= 1)
putchar(num & mask ? '1' : '0');
}
This calculates the value with the top bit set the first time you call the function, irrespective of the vagaries of negative encodings. Just watch out if you call it concurrently in a threaded program.
But, as mentioned, this probably isn't necessary, the number of environments that use the other two encodings would be countable on the fingers of a very careless/unlucky industrial machine operator.
You already have your primary question answered regarding the use of >> rather than =>>. However, from a fundamental standpoint there is no need to buffer the 1 and 0 in an array of int (e.g. int bin_buffer[32];) and there is no need to use the variadic printf function to display int values if all you are doing is outputting the binary representation of the number.
Instead, all you need is putchar() to output '1' or '0' depending on whether any bit is set or clear. You can also make your output function a bit more useful by providing the size of the representation you want, e.g. a byte (8-bits), a word (16-bits), and so on.
For example, you could do:
#include <stdio.h>
#include <limits.h>
/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
*/
void binaryConversion (const unsigned long v, size_t sz)
{
if (!sz) { fprintf (stderr, "error: invalid sz.\n"); return; }
if (!v) { while (sz--) putchar ('0'); return; }
if (sz > sizeof v * CHAR_BIT)
sz = sizeof v * CHAR_BIT;
while (sz--)
putchar ((v >> sz & 1) ? '1' : '0');
}
int main(){
fputs ("byte : ", stdout);
binaryConversion (2, 8);
fputs ("\nword : ", stdout);
binaryConversion (2, 16);
putchar ('\n');
}
Which allows you to set the number of bits you want displayed, e.g.
Example Use/Output
$ ./bin/binaryconversion
byte : 00000010
word : 0000000000000010
There is nothing wrong with your approach, but there may be a simpler way to arrive at the same output.
Let me know if you have further questions.
INT_MIN is a negative number so when you shifted to the right using >>, the most significant bit will still be 1 instead of zero and you will end up in mask=11111...111 all bits have value of 1. Also the mask value is not changing. better use >>= instead. You can try masking on 0x1 and shift the actual value of num instead of the mask like this.
int binaryConversion(int num) {
char bin_buffer[32 + 1]; //+1 for string terminator.
int shifted = num;
for (int i = 31; i >= 0; --i, shifted >>= 1) { //loop 32x
bin_buffer[i] = '0' + (shifted & 0x1);
}
bin_buffer[32] = 0; //terminate the string.
printf("%s", bin_buffer);
}

K&R Exercise 2-7, optimisations?

I'm currently learning C with "The C Programming Language" from K&R. I solved the exercise 2-7, which says:
Write a function invert(x,p,n) that returns x with the n bits that begin at position p inverted (i.e., 1 changed into 0 and vice versa), leaving the other bits unchanged.
Here is my code (I voluntarily used chars here):
#include <stdio.h>
#define NUMBER 235
#define POSITION 2
#define AMOUNT 4
unsigned invert(unsigned char x, char p, char n)
{
unsigned char bitsToInvert = 0, i;
for (i = 1; i < n; i++) { // Make a number n-bits width, full of 1
bitsToInvert |= 1;
bitsToInvert <<= 1;
}
bitsToInvert |= 1;
bitsToInvert <<= p;
x ^= bitsToInvert;
return x;
}
int main()
{
printf("%d\n", invert(NUMBER, POSITION, AMOUNT));
}
Is there any optimisation I could bring to my code? Especially on the for loop which create a number of n 1 bits?
Thanks!
2^n - 1 is always a number with all n LSB bits set.
For eg:
2 ^ 3 - 1 = 7 => 111
2 ^ 5 - 1 = 31 => 11111
In your case, you can do away with the for loop to construct this number by simply saying:
bitsToConvert = (1<<n) - 1;
Dont forget to take care of extreme situations.
An alternative to what Thrustmaster said, that would work for any "n" without the need for specifying it, would be using a bitwise not on an empty value.
variable = ~(variable ^ variable);

How a long data type will be stored in a memory?

My Need:
For any non - negative unsigned long a,
Input a = 5; Ans should be 3
Input a = 12; Ans should be 4
Input a = 1; Ans should be 1
Input a=0 Ans should be 0
i.e to Find the most significant 1 position from the left.
What I have tried:
int count = 0;
if( a!=0 )
do{
count++;
}while( a >>= 1 );
Problem
Takes more time because of while loop and shifting.
Proposed method
If I know how the 4 bytes is stored in memory, (using char*) I will take out the byte, which contains the most significant 1, thus in worst case maximum 8 shifting will suffice to find the answer.
Don't do that. Your method won't work if the most significant byte doesn't contain the bit you're looking for (i. e. if your number is less than 2 ^ (3 * CHAR_BIT)). Why don't you just start from the other end?
unsigned find_msb(unsigned long long n)
{
int bits_max = sizeof(n) * CHAR_BIT - 1;
int i;
for (i = bits_max; i >= 0; i--) {
if ((n >> i) & 1) return i + 1;
}
return 0;
}
I think you are way to worried about efficiency. Worst case is O(n) and frankly it's never going to get any better. Even in an embedded system on a slow processor there's no real need to try and speed up H2CO3's algorithm.
Get it working, then worry about efficiency.

How to form a character byte by assigning values to each of the bits?

I have a C function which accepts a character. I need to extract as well insert bits into that character. I am clear with the extraction part. Can anyone give me an idea of how to insert values to bits?
Pretty vague question, I would suggest you brush up on bitwise operators. This should point you in the right direction.
http://www.cprogramming.com/tutorial/bitwise_operators.html
Since you requested for idea and not exact implementation:
Here is what you can do,
Iterate over each bit and set it as required.
You can set the nth bit (0 indexed as follows)
byteVal = byteVal | (1<<N);
Say you want to check the nth bit of a char:
int checkBit(char c, int n) {
return c & (1 << n);
}
To set the nth bit:
void setBit(char *c, int n) {
*c |= 1 << n;
}
If you want to set the Nth bit in a character to 1, you need to OR it with the value 1 shifted to the left by N positions:
c |= 1 << N;
Sure, simply resort to binary operations. The following function should do exactly what you want, but with a simple interface:
char set8 (char ch, int index) {
if (index >= 1 && index <= 8) {
return (char)(ch | (1 << index - 1));
}
return ch;
}
int n = 0;
set8(n, 1); // Returns 1
set8(n, 2); // Returns 2
set8(n, 3); // Returns 4
...
set8(n, 9); // Returns n (0)
The function uses bitwise-OR to toggle the specified bit. If the index specified is outside the range of a byte (8 bits), then it simply returns the character passed in.

Fastest way to count number of bit transitions in an unsigned int

I'm looking for the fastest way of counting the number of bit transitions in an unsigned int.
If the int contains: 0b00000000000000000000000000001010
The number of transitions are: 4
If the int contains: 0b00000000000000000000000000001001
The number of transitions are: 3
Language is C.
int numTransitions(int a)
{
int b = a >> 1; // sign-extending shift properly counts bits at the ends
int c = a ^ b; // xor marks bits that are not the same as their neighbors on the left
return CountBits(c); // count number of set bits in c
}
For an efficient implementation of CountBits see http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
Fastest depends on your scenario:
As you specified your datatype as constant sized (unsigned int), it is possible with lookup table. But when you need this operation only once the constant overhead to init the table is too big, and scanning+counting through the int is far faster despite.
I guess the overall best would be a combination: Look up table for a byte or word (256 or 64k entries is not so much), and then combine the bytes/words by their last/first bit.
In C/C++ I would do the following:
unsigned int Transitions(unsigned int value)
{
unsigned int result = 0;
for (unsigned int markers = value ^ (value >> 1); markers; markers = markers >> 1)
{
if (markers & 0x01) result++;
}
return result;
}
Here's the code using arithmetic shift + xor and Kernighan's method for bit counting:
int count_transitions(int x)
{
assert((-1 >> 1) < 0); // check for arithmetic shift
int count = 0;
for(x ^= (x >> 1); x; x &= x - 1)
++count;
return count;
}
What language?
I would loop 64 times and then bit shift your number to inspect of the bits, then store the previous bit and compare it to the current one. If it's different, incremember your count.
Ok, with transitions you mean if you walk through the string of 0-s and 1-s, you count each occurance that a 0 follows a 1 or a 1 follows a 0.
This is easy by shifting bits out and counting the changes:
transitions(n)
result = 0
prev = n mod 2
n = n div 2
while n<>0
if n mod 2 <> prev then
result++
prev = n mod 2
fi
n = n div 2
elihw
return result
you can replace the mod and div with shifts.

Resources