I'm working on a method in which I need to perform a right rotation. For instance, I have the binary number 0101110111000111, and after the method is performed, the result should be 1010111011100011. A 16-bit non-negative number is passed as the parameter, and this parameter value will have all the bits moved to the right by 1 bit position and with the low-order bit moved to the high-order position (like the example above).
Here is the code I have written. I converted 0101110111000111 to the decimal value of 24007.
#include <stdlib.h>
#include <stdio.h>
unsigned int rotateRight(unsigned int x);
int main(int argc, char **argv) {
unsigned int n = 24007;
printf("%d\n", rotateRight(n, d));
return 0;
}
/*Function to right rotate n by d bits*/
unsigned int rotateRight(unsigned int x) {
return (x >> 1) | (x << (16-1));
}
My expected result should be the value of 44771, because that is the decimal equivalent to 1010111011100011. However, when I run this program, I get 786673379. Could someone explain why this is happening, and how I could improve my rotation function so I can get the correct answer?
(x << (16-1) shifts the entire 16-bit quantity 15 places to the left and prepends it to the x >> 1. Since int can hold a 32-bit value and therefore doesn't truncate your calculation, you get a 31-bit value as a result.
i.e.
x = 0101 1101 1100 0111
x >> 1 = 0010 1110 1110 0011
x << (16 -1) = 0010 1110 1110 0011 1000 0000 0000 0000
=> (x >> 1) | (x << (16-1))
= 0101110111000111010111011100011 (binary)
= 786673379 (decimal)
A solution would be:
unsigned int rotateRight(unsigned int x) {
return ((x >> 1) | (x << (16-1))) & 0xffff;
}
i.e. do the calculation you're already doing, but keep only the lowest 16 bits.
Alternatively you could use a type like uint16_t to ensure that larger numbers are automatically truncated, subject to your feelings about implicit type conversions and explicit type conversion syntax.
Related
x is an int,
I should be able to get the correct result when 0 is not involved. In attempts to account for the 0 case, I added "& x", which I believe now should return that a number is positive iff x > 0 and x is not 0 (because in c, any number other than 0 evaluates to true, correct?)
But, when running my tests, it says it has failed to evaulate 0x7fffffff as positive and I am not sure why!
Here is my code:
int mask = 0x1;
x = x >> 31;
int lsb = mask & x;
return ( (lsb) ^ 0x1) & (x) )
Edit: I have solved the problem by changing the code to the one below! Feedback is still very much appreciated, or any problems you may spot.
int mask = 0x1;
int lsb = (x >> 31) & mask;
int result = !(lsb ^ 0x1);
return !(result | !x);
If you know the representation is 2's complement, then you can do:
#include <stdio.h>
#define IS_NEG(a) (!!((1 << 31) & (a)))
int main(void)
{
int n;
while(1) {
scanf("%d", &n);
printf("negative: %d\n", IS_NEG(n));
}
return 0;
}
Explanation:
(1 << 31) will take the number 1 and shift it 31 times to the left, thus giving you 1000 0000 0000 0000 0000 0000 0000 0000. If you don't want to use the shift, you could use 0x80000000 too.
& (a) does a bitwise test with that big binary number. Since an AND operation only returns TRUE when both operands are TRUE, it follows that only if your number is negative (in 2's complement representation) that this will return TRUE.
!!(...) This double negation accounts for the fact that when you do that bitwise AND, the returned value by the expression will be (1 << 31) if the number is really negative. So we invert it (giving us zero), than invert it again (giving us 1). Therefore, this ensures that we get a ZERO or a ONE as a final result.
IS_NEG will return 0 on positive numbers AND 0, and returns 1 on all negative numbers.
Since the MSB will be a one when the number is negative, just test that bit. Note that this will only work for 32 bit integers (so you have to check that with a sizeof(int). The example returns 1 if a number is negative, but should be no problem reworking it to return 1 for positive numbers.
Let me know if this doesn't solve the problem. As I understand, you just want to test if any given int is positive/negative.
Edit: From the comments, I made a program to help you see what's going on.
#include <stdio.h>
#define IS_NEG(a) (!!(0x80000000 & (a)))
char buf[65];
/* converts an integer #n to binary represention of #bits bits */
char *bin(int n, unsigned int bits)
{
char *s = buf;
for(bits = (1 << (bits - 1)); bits > 0; bits = bits >> 1)
/* look! double negation again! Why this? :) */
*s++ = !!(n & bits) + 48;
*s = 0;
return buf;
}
int main(void)
{
/* R will be our partial result through-out the loop */
int r, n;
while(1) {
/* get the number */
scanf("%d", &n);
/* this is the inner part of the macro
* after this, we could say IS_NEG "becomes"
* (!!(r))
*/
r = n & 0x80000000;
printf("n & 0x80000000: 0x%x\n", r);
printf(" n = %s\n", bin(n, 32));
printf(" r = %s\n", bin(r, 32));
/* now we print what R is, so you see that the bitwise AND will
* return 0x80000000 on negative numbers. It will also print
* the NEGATION of R...
*
* After the printf(), we just assign the negated value to R.
*/
printf("r = 0x%x, !r = 0x%x\n", r, !r);
r = !r;
printf(" r = %s\n", bin(r, 32));
/* After this, IS_NEG "becomes" (!(r)) */
/* In the MACRO, this would be the second negation. */
printf("r = 0x%x, !r = 0x%x\n", r, !r);
r = !r;
printf(" r = %s\n", bin(r, 32));
/* Now, if R is 0, it means the number is either ZERO or
* POSITIVE.
*
* If R is 1, then the number is negative
*/
}
return 0;
}
https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign
Technically, an int could be a different size on different machines; use of an C99 int32_t from inttypes.h may help with portability. It might not even be encoded in the format you expect, Are there any non-twos-complement implementations of C?.
The really portable easy way, is of course,
static int is_positive(const int a) {
return a > 0;
}
The compiler will probably do a better job optimising it.
Edit: From comments, I came up with this; I tried to make it agnostic of the int-size. It is very much the same style as your own, checking whether the number is negative or zero, and inverting.
#include <stdio.h> /* printf */
#include <limits.h> /* INT_ */
#include <assert.h> /* assert */
/** Assumes a is a 2's-compliment number
and ~INT_MAX = 0b100..00, (checks if negative.) */
static int is_positive(const int a) {
unsigned b = a;
return !((b & ~INT_MAX) | !b);
}
static int is_really_positive(const int a) {
return a > 0;
}
static void test(const int a) {
printf("Number %d. Is positive %d.\n", a, is_positive(a));
assert(is_positive(a) == is_really_positive(a));
}
int main(void) {
test(INT_MIN);
test(-2);
test(-1);
test(0);
test(1);
test(2);
test(INT_MAX);
return 0;
}
Also related, https://stackoverflow.com/a/3532331/2472827.
Given the allowed operators from your comment, ! ~ & ^ | + << >>, edit: with the later constraint of no casts only the second alternative fits:
static int is_positive(unsigned x)
{
return ~x+1 >> (CHAR_BIT*sizeof x-1);
}
Here's the deal: conversion to unsigned is very carefully specified in C: if the signed value is unrepresentable in the unsigned type, one plus the maximum value representable in the unsigned type is added (or subtracted, no idea what prompted them to include this possibility) to the incoming value until the result is representable.
So the result depends only on the incoming value, not its representation. -1 is converted to UINT_MAX, no matter what. This is correct, since the universe itself runs on twos-complement notation . That it also makes the conversion a simple no-op reinterpretation on most CPUs is just a bonus.
You can get a 32-bit wide zero-or-nonzero test using bitwise or and shifts as follows:
int t;
t = x | (x>>16);
t = t | (t >> 8);
t = t | (t >> 4);
t = t | (t >> 2)
t = (t | (t>>1)) & 1;
This sets t to the "OR" of the low 32 bits of x and will 0 if and only if the low 32 bits are all zero. If the int type is 32 bits or less, this will be equivalent to (x != 0). You can combine that with your sign bit test:
return t & (~x >> 31);
To check whether given number is positive or negative. As you mentioned x is an int & I assume its 32-bit long signed int. for e.g
int x = 0x7fffffff;
How above x represented in binary
x => 0111 1111 | 1111 1111 | 1111 1111 | 1111 1111
| |
MSB LSB
Now to check given number is positive or negative using bitwise opaertor, just find out the status of last(MSB or 31st(longint) or 15th(short int)) bit status whether it's 0 or 1, if last bit is found as 0 means given number is positive otherwise negative.
Now How to check last bit(31st) status ? Shift last(31st) bit to 0th bit and perform bitwise AND & operation with 1.
x => 0111 1111 | 1111 1111 | 1111 1111 | 1111 1111
x>>31 => 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000
---------------------------------------------
&
1 => 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001
---------------------------------------------
0000 0000 | 0000 0000 | 0000 0000 | 0000 0000 => its binary of zero( 0 ) so its a positive number
Now how to program above
static inline int sign_bit_check(int x) {
return (x>>31) & 1;
}
And call the sign_bit_check() like
int main(void) {
int x = 0x7fffffff;
int ret = sign_bit_check(x);
if(ret) {
printf("Negative\n");
}
else {
printf("positive \n");
}
return 0;
}
I was thinking this world work, but it does not:
int a = -500;
a = a << 1;
a = (unsigned int)a >> 1;
//printf("%d",a) gives me "2147483148"
My thought was that the left-shift would remove the leftmost sign bit, so right-shifting it as an unsigned int would guarantee that it's a logical shift rather than arithmetic. Why is this incorrect?
Also:
int a = -500;
a = a << 1;
//printf("%d",a) gives me "-1000"
TL;DR: the easiest way is to use the abs function from <stdlib.h>. The rest of the answer involves the representation of negative numbers on a computer.
Negative integers are (almost always) represented in 2's complement form. (see note below)
The method of getting the negative of a number is:
Take the binary representation of the whole number (including leading zeroes for the data type, except the MSB which will serve as the sign bit).
Take the 1's complement of the above number.
Add 1 to the 1's complement.
Prefix a sign bit.
Using 500 as an example,
Take the binary representation of 500: _000 0001 1111 0100 (_ is a placeholder for the sign bit).
Take the 1's-complement / inverse of it: _111 1110 0000 1011
Add 1 to the 1's complement: _111 1110 0000 1011 + 1 = _111 1110 0000 1100. This is the same as 2147483148 that you obtained, when you replaced the sign-bit by zero.
Prefix 0 to show a positive number and 1 for a negative number: 1111 1110 0000 1100. (This will be different from 2147483148 above. The reason you got the above value is because you nuked the MSB).
Inverting the sign is a similar process. You get leading ones if you use 16-bit or 32-bit numbers leading to the large value that you see. The LSB should be the same in each case.
Note: there are machines with 1's complement representation, but they are a minority. The 2's complement is usually preferred because 0 has the same representation, i.e., -0 and 0 are represented as all-zeroes in the 2's complement notation.
Left-shifting negative integers invokes undefined behavior, so you can't do that. You could have used your code if you did a = (unsigned int)a << 1;. You'd get 500 = 0xFFFFFE0C, left-shifted 1 = 0xFFFFFC18.
a = (unsigned int)a >> 1; does indeed guarantee logical shift, so you get 0x7FFFFE0C. This is decimal 2147483148.
But this is needlessly complex. The best and most portable way to change the sign bit is simply a = -a. Any other code or method is questionable.
If you however insist on bit-twiddling, you could also do something like
(int32_t)a & ~(1u << 31)
This is portable to 32 bit systems, since (int32_t) guarantees two's complement, but 1u << 31 assumes 32 bit int type.
Demo:
#include <stdio.h>
#include <stdint.h>
int main (void)
{
int a = -500;
a = (unsigned int)a << 1;
a = (unsigned int)a >> 1;
printf("%.8X = %d\n", a, a);
_Static_assert(sizeof(int)>=4, "Int must be at least 32 bits.");
a = -500;
a = (int32_t)a & ~(1u << 31);
printf("%.8X = %d\n", a, a);
return 0;
}
As you put in the your "Also" section, after your first left shift of 1 bit, a DOES reflect -1000 as expected.
The issue is in your cast to unsigned int. As explained above, the negative number is represented as 2's complement, meaning the sign is determined by the left most bit (most significant bit). When cast to an unsigned int, that value no longer represents sign but increases the maximum value your int can take.
Assuming 32 bit ints, the MSB used to represent -2^31 (= -2147483648) and now represents positive 2147483648 in an unsigned int, for an increase of 2* 2147483648 = 4294967296. Add this to your original value of -1000 and you get 4294966296. Right shift divides this by 2 and you arrive at 2147483148.
Hoping this may be helpful: (modified printing func from Print an int in binary representation using C)
void int2bin(int a, char *buffer, int buf_size) {
buffer += (buf_size - 1);
for (int i = buf_size-1; i >= 0; i--) {
*buffer-- = (a & 1) + '0';
a >>= 1;
}
}
int main() {
int test = -500;
int bufSize = sizeof(int)*8 + 1;
char buf[bufSize];
buf[bufSize-1] = '\0';
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: -500 (4294966796): 11111111111111111111111000001100
test = test << 1;
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: -1000 (4294966296): 11111111111111111111110000011000
test = 500;
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: 500 (500): 00000000000000000000000111110100
return 0;
}
I've been looking at posts about masks, but I still can't get my head around how to extract certain bits from a number in C.
Say if we have an integer number, 0001 1010 0100 1011, its hexadecimal representation is 0x1A4B, right? If I want to know the 5th to 7th number, which is 101 in this case, shall I use int mask= 0x0000 1110 0000 0000, int extract = mask&number?
Also, how can I check if it is 101? I guess == won't work here...
Masking is done by setting all the bits except the one(s) you want to 0. So let's say you have a 8 bit variable and you want to check if the 5th bit from the is a 1. Let's say your variable is 00101100. To mask all the other bits we set all the bits except the 5th one to 0 using the & operator:
00101100 & 00010000
Now what this does is for every bit except the 5th one, the bit from the byte on the right will be 0, so the result of the & operation will be 0. For the 5th bit, however, the value from the right bit is a 1, so the result will be whatever the value of hte 5th bit from the left byte is - in this case 0:
Now to check this value you have to compare it with something. To do this, simply compare the result with the byte on the right:
result = (00101100 & 00010000) == 00000000
To generalize this, you can retrieve any bit from the lefthand byte simply by left-shifting 00000001 until you get the bit you want. The following function achieves this:
int getBit(char byte, int bitNum)
{
return (byte & (0x1 << (bitNum - 1)))
}
This works on vars of any size, whether it's 8, 16, 32 or 64 (or anything else for that matter).
Assuming the GCC extension 0b to define binary literals:
int number = 0b0001101001001011; /* 0x1A4B */
int mask = 0b0000111000000000; /* 0x0E00 */
/* &'ed: 0b0000101000000000; 0x0A00 */
int extract = mask & number; /* 0x0A00 */
if (extract == 0b0000101000000000)
/* Or if 0b is not available:
if (extract == 0x0a00 ) */
{
/* Success */
}
else
{
/* Failure */
}
You need to mask and shift. Either shift the value you are comparing to, or the value you are comparing. I find it easier to think about by shifting the value you are comparing to. So if you're trying to extract the 5th to 7th digits (from the left), you shift right 9 positions (16-7) so that the 7th digit is now the rightmost, then apply 0x7 (111 in binary) as a mask to get only the rightmost three binary digits
int i = 0x1A4B;
if (((i >> 9) & 0x07) == 0x05) { // 0x05 = 101 in binary
//do what you need to
}
First, the digits in binary are (usually) counted from the right (10th and 12th digit) or you say 5th and 7th most significant digits.
int mask = 0x0E00; // 0000 1110 0000 0000;
int extract = mask & number;
results in:
extract = 0000 1010 0000 0000
You can do
if (extract == 0x0A00 /*0000 1010 0000 0000*/){}
to test, or:
if (( extract >> 9 ) == 0x05){}
Both of the statements in the if will return true with your sample number.
Usually with a mask you will find yourself testing a single digit. You could use a function like this to test it:
bool digit_value( unsigned int number, unsigned int digit)
{
return (1 << digit) & number;
}
int main()
{
unsigned int number = 0x1A4B;
int should_be_three = 0;
should_be_three += digit_value(number, 10);
should_be_three += !digit_value(number, 11);
should_be_three += digit_value(number, 12);
printf("%s", (should_be_three == 3?"it worked":"it didn't work"));
return 0;
}
It may be simpler to check bits one-by-one, not all at once.
At first, you create mask for interested bit:
int fifthBitMask = 1 << 4;
int fifthBitResult = number & fifthBitMask;
int seventhBitMask = 1 << 6;
int seventhBitResult = number & seventhBitMask;
Now, you can compare results with zero OR with mask.
Comparing with zero can be omitted, so you can just use simple if:
if (fifthBitResult && seventhBitResult)
{
//your code here
}
Also, you can compare with masks. After operation &, in result will set only bits, which was set in mask.
So, it could like this:
if (fifthBitResult == fifthBitMask && seventhBitResult == seventhBitMask)
{
// your code here
}
So, if result of operation is equals to mask, you can do this with one operation:
int mask = 0x5 << 4; // 0x5 is hex representation of 101b
int result = number & mask;
if (result == mask)
{
// your code here
}
shall I use int mask= 0x0000 1110 0000 0000, int extract = mask&number?-
Yes, you can do this.
Also, how can I check if it is 101?
Sure you can check this-
0000 1010 0000 0000 which is 1280 in int.
extract== 1280
First of all, your calculation for bits 7-6-5 is incorrect. You stated it was 101, but it is 010 (for x1a43).
Second of all, to get these bits (the value represented by these bits) you should do &0xE0.
int my_bits_from_5to7 = number & 0xE0;
I have do not have much knowledge of C and I'm stuck with a problem since one of my colleague is on leave.
I have a 32 bit number and i have to extract bits from it. I did go through a few threads but I'm still not clear how to do so. I would be highly obliged if someone can help me.
Here is an example of what I need to do:
Assume hex number = 0xD7448EAB.
In binary = 1101 0111 0100 0100 1000 1110 1010 1011.
I need to extract the 16 bits, and output that value. I want bits 10 through 25.
The lower 10 bits (Decimal) are ignored. i.e., 10 1010 1011 are ignored.
And the upper 6 bits (Overflow) are ignored. i.e. 1101 01 are ignored.
The remaining 16 bits of data needs to be the output which is 11 0100 0100 1000 11 (numbers in italics are needed as the output).
This was an example but I will keep getting different hex numbers all the time and I need to extract the same bits as I explained.
How do I solve this?
Thank you.
For this example you would output 1101 0001 0010 0011, which is 0xD123, or 53,539 decimal.
You need masks to get the bits you want. Masks are numbers that you can use to sift through bits in the manner you want (keep bits, delete/clear bits, modify numbers etc). What you need to know are the AND, OR, XOR, NOT, and shifting operations. For what you need, you'll only need a couple.
You know shifting: x << y moves bits from x *y positions to the left*.
How to get x bits set to 1 in order: (1 << x) - 1
How to get x bits set to 1, in order, starting from y to y + x: ((1 << x) -1) << y
The above is your mask for the bits you need. So for example if you want 16 bits of 0xD7448EAB, from 10 to 25, you'll need the above, for x = 16 and y = 10.
And now to get the bits you want, just AND your number 0xD7448EAB with the mask above and you'll get the masked 0xD7448EAB with only the bits you want. Later, if you want to go through each one, you'll need to shift your result by 10 to the right and process each bit at a time (at position 0).
The answer may be a bit longer, but it's better design than just hard coding with 0xff or whatever.
OK, here's how I wrote it:
#include <stdint.h>
#include <stdio.h>
main() {
uint32_t in = 0xd7448eab;
uint16_t out = 0;
out = in >> 10; // Shift right 10 bits
out &= 0xffff; // Only lower 16 bits
printf("%x\n",out);
}
The in >> 10 shifts the number right 10 bits; the & 0xffff discards all bits except the lower 16 bits.
I want bits 10 through 25.
You can do this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;
Or this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;
I combined the top 2 answers above to write a C program that extracts the bits for any range of bits (not just 10 through 25) of a 32-bit unsigned int. The way the function works is that it returns bits lo to hi (inclusive) of num.
#include <stdio.h>
#include <stdint.h>
unsigned extract(unsigned num, unsigned hi, unsigned lo) {
uint32_t range = (hi - lo + 1); //number of bits to be extracted
//shifting a number by the number of bits it has produces inconsistent
//results across machines so we need a special case for extract(num, 31, 0)
if(range == 32)
return num;
uint32_t result = 0;
//following the rule above, ((1 << x) - 1) << y) makes the mask:
uint32_t mask = ((1 << range) -1) << lo;
//AND num and mask to get only the bits in our range
result = num & mask;
result = result >> lo; //gets rid of trailing 0s
return result;
}
int main() {
unsigned int num = 0xd7448eab;
printf("0x%x\n", extract(num, 10, 25));
}
I suppose sizeof(char) is one byte. Then when I write following code,
#include<stdio.h>
int main(void)
{
char x = 10;
printf("%d", x<<5);
}
The output is 320
My question is, if char is one byte long and value is 10, it should be:
0000 1010
When I shift by 5, shouldn't it become:
0100 0001
so why is output 320 and not 65?
I am using gcc on Linux and checked that sizeof(char) = 1
In C, all intermediates that are smaller than int are automatically promoted to int.
Therefore, your char is being promoted to larger than 8 bits.
So your 0000 1010 is being shifted up by 5 bits to get 320. (nothing is shifted off the top)
If you want to rotate, you need to do two shifts and a mask:
unsigned char x = 10;
x = (x << 5) | (x >> 3);
x &= 0xff;
printf("%d", x);
It's possible to do it faster using inline assembly or if the compiler supports it, intrinsics.
Mysticial is right. If you do
char x = 10;
printf("%c", x);
It prints "#", which, if you check your ASCII table, is 64.
0000 1010 << 5 = 0001 0100 0000
You had overflow, but since it was promoted to an int, it just printed the number.
Because what you describe is a rotate, not a shift. 0 is always shifted in on left shifts.