Different bits of two given integers - c

Hey so I have been asked to get the number of different bits between two integers.
I have written the code below which seem to work but only for positive numbers.
I would love to know what am I doing wrong.
printf("Enter 2 numbers:\n");
scanf("%d %d", &num1, &num2);
xor_num = num1 ^ num2;
while (xor_num != 0) {
if (xor_num & 1) {
xor_num = xor_num >> 1;
bits_on += 1;
}
else
xor_num = xor_num >> 1;
}
printf("There are %d diffrent bits\n", bits_on);

Shifting bits on a negative integer has implementation-defined behavior. In your case the sign bit (the most significant bit) is most likely not shifted so the variable xor_num never approaches zero and the loop is infinite. Instead you need to work on an unsigned integer. When you use the scanf function you also need to make sure that the input is valid. It is also a good idea to break out the code which calculates the number of bits into a separate function. Here is one way to do it:
#include <stdio.h>
#include <stdlib.h>
int BitCount(int x)
{
int result = 0;
unsigned int y = x;
while (y != 0) {
result += (y & 1);
y >>= 1;
}
return result;
}
int main(void)
{
int n, x, y;
printf("Enter 2 numbers:\n");
n = scanf("%d %d", &x, &y);
if (n == 2) {
printf("There are %d diffrent bits\n", BitCount(x ^ y));
} else {
fprintf(stderr, "wrong input\n");
exit(EXIT_FAILURE);
}
return 0;
}

When shifting negative values right, it is common for C implementations to copy the sign bit and leave it unchanged, rather than zeroing it. For example, where the four unsigned bits 1000 would be shifted to 0100 and then 0010 0001, and 0000, the four bits with a leading sign bit 1000 would be shifted to 1100, 1110, and then 1111. (The C standard leaves it to the implementation to define this behavior, per C 2018 6.5.7 5.) In this case, when xor_num is negative, xor_num >> 1 leaves the sign bit set, so it never becomes non-negative.
The easiest way to deal with this, presuming you are using int types, is to use unsigned xor_num = num1 ^ num2;. If your C implementation uses two’s complement do, which all regular implementations today do, the conversion from signed int to unsigned int will produce the same bits in xor_num but the shift with xor_num >> 1 will be a logical shift, which zeros the sign bit.

Related

How to bit shift "x" with "y"?

I have some trouble with a bit-shift program.
The challenge is to write a program which can shift an unsigned int a number of steps to the left. Both integers are given as input by the user. Thus, given two integers (x and y), the bits in x shall be moved y steps to the left, and the bits which are lost on the left side should be moved to the right. Namely, the bits which are lost outside the most significant are placed in the least significant positions.
To solve the challenge, I have made the following attempt:
#include <stdio.h>
#include <utility.h>
unsigned int bitshift(unsigned int a, unsigned int b)
{
a<<b;
b>>a;
return a,b;
}
int main (void)
{
unsigned int x, y;
printf("Enter two integers (smaller than 32) please:\n");
scanf("%u%u", &x, &y);
printf("Your integers are %u and %u.\n", x, y);
printf("In hexadecimal-format, your integers are %08x and %08x.\n", x, y);
printf("We are now going to perform a bit shift operation\n");
printf("The result of the bitshift operation is:\n");
printf("%u and %u\n", bitshift(x,y));
printf("In hexadecimal: %08x and %08x\n", bitshift(x,y));
while(!KeyHit());
return 0;
}
However, I'm getting an error message when compiling, e.g. "not enough parameters", which I do not understand.
But what I am most wondering is if the bitshift function will do the job?
This is a modification of Barmar's (now deleted) solution for function bitshift with improvements suggested in comments.
Unfortunately, C does not have operators to rotate the bits in a value as might be available in the CPU's instruction set. That's why the operation can be done by moving the least significant bits to the left, moving the most significant bits to the right and combining the results.
To calculate the shift width for shifting the most significant bits to the right, the number of bits in the data type must be calculated using sizeof.
Note that a shift width greater than or equal to the number of bits in the value is undefined behavior (UB). That's why the shift width is calculated modulo the number of bits in the value. Additionally a left shift of 0 would result in UB in the right shift.
#include <stdio.h>
// get CHAR_BITS to make code portable for unusual platforms
#include <limits.h>
unsigned int bitshift(unsigned int a, unsigned int b)
{
// modulo operation to prevent undefined behavior
b %= sizeof a * CHAR_BIT; // sizeof a * 8 on usual platforms
// prevent undefined behavior for right shift
if(b == 0) return a;
unsigned int upper = a << b;
// not portable for unusual platforms
// unsigned int lower = a >> (sizeof a * 8 - b);
unsigned int lower = a >> (sizeof a * CHAR_BIT - b);
return upper | lower;
}
int main (void)
{
unsigned int x, y;
printf("Enter two integers (smaller than 32) please:\n");
scanf("%u%u", &x, &y);
printf("Your integers are %u and %u.\n", x, y);
printf("In hexadecimal-format, your integers are %08x and %08x.\n", x, y);
printf("We are now going to perform a bit shift operation\n");
printf("The result of the bitshift operation is:\n");
printf("%u\n", bitshift(x,y));
printf("In hexadecimal: %08x\n", bitshift(x,y));
return 0;
}
Example input/output:
Enter two integers (smaller than 32) please:
1234567890 12
Your integers are 1234567890 and 12.
In hexadecimal-format, your integers are 499602d2 and 0000000c.
We are now going to perform a bit shift operation
The result of the bitshift operation is:
1613571225
In hexadecimal: 602d2499
Enter two integers (smaller than 32) please:
246 28
Your integers are 246 and 28.
In hexadecimal-format, your integers are 000000f6 and 0000001c.
We are now going to perform a bit shift operation
The result of the bitshift operation is:
1610612751
In hexadecimal: 6000000f
It is enough tho shift right to get the bits which will be shifted out and or it with the value shifted left. To avoid UBs number of bits should be checked.
unsigned rol(unsigned val, unsigned nbits)
{
if(nbits && nbits < CHAR_BIT * sizeof(val))
{
val = (val >> (CHAR_BIT * sizeof(val) - nbits)) | (val << nbits);
}
return val;
}
You actually want to rotate the bits.
// Rotate the bits of a by b to the left and return the result
unsigned int bitshift(unsigned int a, unsigned int b)
{
for (unsigned int i = 0; i < b; i++)
{
unsigned int lowbit = 0;
if (a & 0x80000000)
lowbit = 1;
a <<= 1;
a |= lowbit;
}
return a;
}
This assumes unsigned int is 32 bits. You should be able to adapt it for 64 bits.
Disclaimer:
This is a very naive method though. If you need speed, you should avoid the loop. This can be done but it's more tricky.

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);
}

Getting the mantissa (of a float) of either an unsigned int or a float (C)

So, i am trying to program a function which prints a given float number (n) in its (mantissa * 2^exponent) format. I was abled to get the sign and the exponent, but not the mantissa (whichever the number is, mantissa is always equal to 0.000000). What I have is:
unsigned int num = *(unsigned*)&n;
unsigned int m = num & 0x007fffff;
mantissa = *(float*)&m;
Any ideas of what the problem might be?
The C library includes a function that does this exact task, frexp:
int expon;
float mant = frexpf(n, &expon);
printf("%g = %g * 2^%d\n", n, mant, expon);
Another way to do it is with log2f and exp2f:
if (n == 0) {
mant = 0;
expon = 0;
} else {
expon = floorf(log2f(fabsf(n)));
mant = n * exp2f(-expon);
}
These two techniques are likely to give different results for the same input. For instance, on my computer the frexpf technique describes 4 as 0.5 × 23 but the log2f technique describes 4 as 1 × 22. Both are correct, mathematically speaking. Also, frexp will give you the exact bits of the mantissa, whereas log2f and exp2f will probably round off the last bit or two.
You should know that *(unsigned *)&n and *(float *)&m violate the rule against "type punning" and have undefined behavior. If you want to get the integer with the same bit representation as a float, or vice versa, use a union:
union { uint32_t i; float f; } u;
u.f = n;
num = u.i;
(Note: This use of unions is well-defined in C since roughly 2003, but, due to the C++ committee's long-standing habit of not paying sufficient attention to changes going into C, it is not officially well-defined in C++.)
You should also know IEEE floating-point numbers use "biased" exponents. When you initialize a float variable's mantissa field but leave its exponent field at zero, that gives you the representation of a number with a large negative exponent: in other words, a number so small that printf("%f", n) will print it as zero. Whenever printf("%f", variable) prints zero, change %f to %g or %a and rerun the program before assuming that variable actually is zero.
You are stripping off the bits of the exponent, leaving 0. An exponent of 0 is special, it means the number is denormalized and is quite small, at the very bottom of the range of representable numbers. I think you'd find if you looked closely that your result isn't quite exactly zero, just so small that you have trouble telling the difference.
To get a reasonable number for the mantissa, you need to put an appropriate exponent back in. If you want a mantissa in the range of 1.0 to 2.0, you need an exponent of 0, but adding the bias means you really need an exponent of 127.
unsigned int m = (num & 0x007fffff) | (127 << 23);
mantissa = *(float*)&m;
If you'd rather have a fully integer mantissa you need an exponent of 23, biased it becomes 150.
unsigned int m = (num & 0x007fffff) | ((23+127) << 23);
mantissa = *(float*)&m;
In addition to zwol's remarks: if you want to do it yourself you have to acquire some knowledge about the innards of an IEEE-754 float. Once you have done so you can write something like
#include <stdlib.h>
#include <stdio.h>
#include <math.h> // for testing only
typedef union {
float value;
unsigned int bits; // assuming 32 bit large ints (better: uint32_t)
} ieee_754_float;
// clang -g3 -O3 -W -Wall -Wextra -Wpedantic -Weverything -std=c11 -o testthewest testthewest.c -lm
int main(int argc, char **argv)
{
unsigned int m, num;
int exp; // the exponent can be negative
float n, mantissa;
ieee_754_float uf;
// neither checks nor balances included!
if (argc == 2) {
n = atof(argv[1]);
} else {
exit(EXIT_FAILURE);
}
uf.value = n;
num = uf.bits;
m = num & 0x807fffff; // extract mantissa (i.e.: get rid of sign bit and exponent)
num = num & 0x7fffffff; // full number without sign bit
exp = (num >> 23) - 126; // extract exponent and subtract bias
m |= 0x3f000000; // normalize mantissa (add bias)
uf.bits = m;
mantissa = uf.value;
printf("n = %g, mantissa = %g, exp = %d, check %g\n", n, mantissa, exp, mantissa * powf(2, exp));
exit(EXIT_SUCCESS);
}
Note: the code above is one of the quick&dirty(tm) species and is not meant for production. It also lacks handling for subnormal (denormal) numbers, a thing you must include. Hint: multiply the mantissa with a large power of two (e.g.: 2^25 or in that ballpark) and adjust the exponent accordingly (if you took the value of my example subtract 25).

Flipping certain bit in an integer (C language)

I'm trying to get my program to work where a certain bit is being flipped. I have this function called flipbit(int *p, int m). The user needs to input a digit and a bit number. Let's say the user gives the number 8 (00001000) and the bit number 2, so the 2nd bit in 8 should be flipped, which becomes 00001010. How can I program this?
EDIT: I made a stupid mistake, I want to count starting from 0, so the 2nd bit in 8 flipped is actually 00001100 instead of 00001010.
#include <stdio.h>
#include <stdlib.h>
void flipbit(int *p, int m) {
int digit;
digit = *p;
int bit;
bit = &m;
int result;
//printf("The numbers are %d %d", digit, bit);
printf("%d", result);
}
int main() {
int number1;
int number2;
printf("Give number and bit: ");
scanf("%d, %d",&number1, &number2);
flipbit(&number1, &number2);
return 0;
}
Given the bit to flip, you first need to create a mask. Do that by taking the value 1 and left shifting it by the bit number.
Once you have that mask, use the bitwise XOR operator ^ to flip the bit.
int mask = 1 << m;
*p = *p ^ mask;
When checking your source code, there are mixture between pointer and value.
To comply the call of your flipbit() function with the declaration, the call should be:
// first parameter is a pointer and second parameter is a value
flipbit(&number1, number2); // void flipbit(int *p, int m);
Inside the flipbit() function, the mixture continues because digit is a value and p is a pointer. The code should be:
int digit;
// 'digit' is a value and 'p' is a pointer
digit = p[0]; // 'digit' is the first value pointed by 'p'
Same error kind of error with the 'bit' parameter
int bit;
// 'bit' is a value and 'm' is a value
bit = m;
And the result to flip a bit is the XOR operation.
the bit number 2, so the 2nd
Due to your specification, you have to shift only of (bit - 1).
So, in your case:
0x0001(or 0000.0000.0000.0001b) << (2 - 1) = 0x0002(or 0000.0000.0000.0010b)
result is 0x0010(or 0000.0000.0000.1000b) XOR 0x0002(or 0000.0000.0000.0010b) = 0x0012(or 0000.0000.0001.0010b).
int result;
result = digit ^ (0x0001 << (bit - 1));
Did you enter '9, 1' to comply with the scanf("%d, %d",..) ?

Bit Level Operators

One of the few programming assignments I had due was dealing with bit level operators and I was hoping I did this correctly.
#include <stdio.h>
int main(void){
int x;
printf("Enter an x: ");
scanf("%x", &x);
printf("X = %d\n", x);
// Any bit in x is 1
x && printf("A bit in x is 1!\n");
// Any bit in x is 0
~x && printf("A bit in x is 0!\n");
// Least significant byte of x has a bit of 1
(x & 0xFF) && printf("A bit in least significant byte of x is 1!\n");
// Most significant byte of x has a bit of 0
int most = (x & ~(0xFF<<(sizeof(int)-1<<3)));
most && printf("A bit in the most significant byte of x is 0!\n");
return 0;
}
The assignment restricted what we could use so there could be no loops or conditionals and many other restrictions. I get a bit confused with the bit level operators so I was just hoping if there are any errors I could fix it and learn why it was wrong. Thanks.
You shouldn't use signed integers for these operations, because some cases result in undefined / implementation-defined behaviour: Arithmetic bit-shift on a signed integer
int most = (x & ~(0xFF<<(sizeof(int)-1<<3)));
You should negate x, not the right hand side:
int most = (~x & (0xFF<<(sizeof(int)-1<<3)));

Resources