Bitwise Arithmetic in C: Checking if a number is positive - c

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

Related

How to swap first and last nibbles in given integer [32 bits]

Suppose :
No = 77
77 in binary [32 bits] : 0000 0000 0000 0000 0000 0000 0100 1101
I have to swap first and last nibble:
i.e : 1101 0000 0000 0000 0000 0000 0100 0000
I was doing something like this:
no << 32 | no >> 32
Then in a loop anding it with 1 and printing. But it does not work out.
#include<stdio.h>
int main()
{
int decimalNumber;
printf("Enter your decimal number: ");
scanf("%d", &decimalNumber);
int i, j;
/* Binary conversion */
for(i=31;i>=0;i--)
{
printf("%d", (decimalNumber >> i) & 1);
}
printf("\n");
printf("After nibble swapping: \n");
/* Nibble swapping */
decimalNumber = (decimalNumber>>28) | (decimalNumber<<28);
for(i=31;i>=0;i--)
{
printf("%d",((decimalNumber>>i)&1 ? 1 : 0));
}
printf("\n");
return 0;
}
Given an unsigned integer d and b number of bits where b <= CHAR_BIT * sizeof(d) / 2 you obtain the result by bitwise OR of these components:
Left shift the lower b bits to the top (sizeof (d) - (b) is 28 bits in this case). When you left shift the lower bits become 0. With example data the value is 0x8000000.
The left followed by right shift clears the top b bits, and the right followed by left shift clears the lower b bits. With the example data the value is 0x02345670. This equivalent bitwise AND of the mask 0x0ffffff0 for a 32-bit number. The shift works for any unsigned integer type irregardless of size.
Right shift the top b bits to the bottom. When you right shift the upper b bits become zero. With the example data the value is 0x00000001.
#include <limits.h>
#include <stdio.h>
#include <stdint.h>
#define SWAP_BITS(d, b) \
/* 1 */ (d) << CHAR_BIT * sizeof (d) - (b) |\
/* 2 */ (d) << (b) >> (b) >> (b) << (b) |\
/* 3 */ (d) >> CHAR_BIT * sizeof (d) - (b)
int main() {
uint32_t d = 0x12345678;
printf("%x\n%x\n", d, SWAP_BITS(d, 4));
}
and the outcome is:
82345671
swap first and last nibbles in given integer (32 bits)
OP's decimalNumber = (decimalNumber>>28) | (decimalNumber<<28); fails as the | or's the data, not replace it. Also shifting by 28 shifts the middle bits, which need to remain in place.
Use unsigned types to not shift into or out of the sign bit.
For a fixed sized tasks, consider using fixed sized types from #include <stdint.h>.
Print data with %X to better see what is happening.
uint32_t uvalue = decimalNumber;
printf("Before %lu\n", (unsigned long) uvalue); // In decimal
printf("Before 0x%lX\n", (unsigned long) uvalue); // In hexadecimal
// Get first (most significant) and last (least significant) nibble.
uint32_t first_nibble = uvalue >> (32-4);
uint32_t last_nibble = uvalue & 0xF;
// zero out the first and last nibble.
uvalue &= 0x0FFFFFF0;
// Now "or" in the replacement nibbles.
uvalue |= first_nibble;
uvalue |= last_nibble << (32-4);
printf("After 0x%lX\n", (unsigned long) uvalue);
printf("After %lu\n", (unsigned long) uvalue);
For those who like one-liners
printf("After %lu\n", (unsigned long) (
(((uint32_t) decimalNumber) & 0xF) << 28) |
((uint32_t) decimalNumber) & 0x0FFFFFF0) |
((uint32_t) decimalNumber) >> 28) |
));
Some would consider the first nibble as the least significant nibble. Whatever is first or last makes little difference here as they are swapped.

Right rotation of a 16-bit non-negative number?

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.

how integer is promoted to unsigned integer

#include<stdio.h>
void main()
{
int a = -1;
unsigned int b =15;
if(b==a)
printf ("b is equal to a");
}
The output is empty. negative integers are stored as 2's complement of same postive number .When a integer is compared to unsigned int integer is promoted to unsigned int by considering the 2's complement as unsigned int which is 15 here but the output is empty eventhough the 2's complement of -1 is 15
The variable a and b
int a = -1; /* its a sign ed int, it takes 4 bytes */
unsigned int b =15;/* its a unsigned int */
And its looks like below
a = -1 => 1111 1111 | 1111 1111 | 1111 1111 | 1111 1111
b = 15 => 0000 0000 | 0000 0000 | 0000 0000 | 0000 1111
MSB LSB
Now when you compare a and b like
if(b==a) {
/* some code */
}
Here you are doing comparison == between two different types(a is of signed type & b is of unsigned type). So implicitly compiler will convert/promote sign int to unsigned int & then it will perform comparison ==. See this http://port70.net/~nsz/c/c11/n1570.html#6.3.1.8 for arithmetic conversation rules.
Now What is the unsigned equivalent of a or -1 ? Its all one's in 4 byte i.e 4294967295. So now it looks like
if(15==4294967295) { /*its false */
/* some code */
}
Since if condition is false, your code doesn't print anything.
If you change variable b to be
unsigned int b = 4294967295;
(This does assume int is being stored as 32 bits)
The print statement will run. See, https://stackoverflow.com/a/2084968/7529976

Negative numbers: How can I change the sign bit in a signed int to a 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;
}

Mask and extract bits in C

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;

Resources