I'm working on making a logical right shift function in C using only bitwise operators. Here's what I have:
int logical_right_shift(int x, int n)
{
int size = sizeof(int); // size of int
// arithmetic shifts to create logical shift, return 1 for true
return (x >> n) & ~(((x >> (size << 3) - 1) << (size << 3) -1)) >> (n-1);
}
This actually works for all cases except if n = 0. I've been trying to figure out a way to fix it so it will work for n = 0 as well, but I'm stuck.
int lsr(int x, int n)
{
return (int)((unsigned int)x >> n);
}
This is what you need:
int logical_right_shift(int x, int n)
{
int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << size) >> n) << 1);
}
Explain
x >> n shifts n bits right. However, if x is negative, the sign bit (left-most bit) will be copied to its right, for example:
Assume every int is 32 bits here, let
x = -2147483648 (10000000 00000000 00000000 00000000), then
x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912 (11100000 00000000 00000000 00000000)
and so on.
So we need to erase out those sign extra sign bits when n is negative.
Assume n = 5 here:
0x1 << size moves 1 to the left-most position:
(10000000 00000000 00000000 00000000)
((0x1 << size) >> n) << 1 copies 1 to its n-1 neighbors:
(11111000 00000000 00000000 00000000)
~((0x1 << size) >> n) << 1! reverses all bits:
(00000111 11111111 11111111 11111111)
so we finally obtain a mask to extract what really need from x >> n:
(x >> n) & ~(((0x1 << size) >> n) << 1)
the & operation does the trick.
And the total cost of this function is 6 operations.
Just store your int in an unsigned int, and perform >> upon it.
(The sign is not extended or preserved if you use unsigned int)
http://en.wikipedia.org/wiki/Logical_shift
I think problem is in your ">> (n-1)" part. If n is 0 then left part will be shift by -1.
So,here is my solution
int logical_right_shift(int x, int n)
{
int mask = ~(-1 << n) << (32 - n);
return ~mask & ( (x >> n) | mask);
}
Derived from php's implementation of logical right shifting
function logical_right_shift( i , shift ) {
if( i & 2147483648 ) {
return ( i >> shift ) ^ ( 2147483648 >> ( shift - 1 ) );
}
return i >> shift;
}
For 32bit platforms only.
As with #Ignacio's comment, I don't know why you would want to do this (without just doing a cast to unsigned like in the other answers), but what about (assuming two's complement and binary, and that signed shifts are arithmetic):
(x >> n) + ((1 << (sizeof(int) * CHAR_BIT - n - 1)) << 1)
or:
(x >> n) ^ ((INT_MIN >> n) << 1)
Milnex's answer is great and has an awesome explanation, but the implementation unfortunately fails due to the shift by total size. Here is a working version:
int logicalShift(int x, int n) {
int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}
To have 1 as the most significant bit, and all zeroes elsewhere, we need to shift 0x1 by number of bits - 1. I am submitting my own answer because my edit to the accepted answer was somehow rejected.
int logicalShift(int x, int n) {
int mask = x>>31<<31>>(n)<<1;
return mask^(x>>n);
}
Only for 32 bits
Related
Me and my group of 4 people are both completely blanking on how to correctly do an arithmetic left shift of an int x, by an amount of n bits.
It is a for a homework problem on bit manipulation for C. We are not allowed to use loops, if statements, or any operations over 15. I've attached the code given below. Also, the simple solution x << n does not work, even though I'm sure we are missing something obvious. If anyone could help or provide guidance, it would be much appreciated.
/*
* arithLeftShift - Do an arithmetic left shift of x by n bits.
* Can assume that 0 <= n <= 31
* Examples: arithLeftShift(0x87654321,4) = 0xF6543218
* Legal ops: ~ & ^ | + << >> !
* Max ops: 15
* Rating: 3
*/
int arithLeftShift(int x, int n) {
return 0;
}
Current error message:
Test arithLeftShift(-2147483648[0x80000000],1[0x1]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000
Actually, It is not arithmetic left shift.It's your arithLeftShift with your sign bit needn't a left shift. And the high bits needed to be shifted to the low position, It looks like a cycle shift.
#include<stdio.h>
int main()
{
arithLeftShift(0x87654321,4);
}
int arithLeftShift(int x,int n)
{
int temp,i; //define two auto variables,
i=x>>(32-n);//i for x's high n bits.
temp=x<<n;//temp for x left shift n bits
if(x>0)//sign bit is 0,
{
x=temp+i;
x=x>0?x:x^0x80000000;//change the x sign bit is 0;
}
else
{//when you do right shift, there will be different with different compliers and your x.
if(i>0){//This means when you do right shift, 0 be inserted into high bits.
x=temp+i;
}
else
{
i=(0x80000000>>(32-n));
x=temp+i;
}
x=x>0?~(x^(~0x80000000)):x;//change the x sign bit is 1
printf("%x\n",x);
}
}
Your ask seems to be to "Rotate" the integer "Left", "n" number of times but retain the "Sign Bit"(MSB) if set.
One solution would be......
#include <stdio.h>
#define INT_BITS 32
int arithLeftShift(int x, int n) {
int res;
res = (x << n | (x >> (INT_BITS - n) & ~(~0 << n))) | x & (~0 << (INT_BITS - 1));
return res;
}
int main(){
int x = 0x87654321;
int n = 4;
printf("0x%x\n",arithLeftShift(x,n));
}
Explanation:
(x << n)
Left shift x, n times - the last n bits are zero.
(x >> (INT_BITS - n) & ~(~0 << n))
Right shift x (INT_BITS - n) times to put the first n bits at the correct position and "AND" it with ~(~0 << n) to set the upper bits to zero.This will take care of "sign extension", if any.
(x << n | (x >> (INT_BITS - n) & ~(~0 << n)))
"OR" them to perform the "Rotate Left" operation.
x & (~0 << (INT_BITS - 1)
Left shift "-1", 31 times and "AND" it with x to check if the MSB of x is set.
(x << n | (x >> (INT_BITS - n) & ~(~0 << n))) | x & (~0 << (INT_BITS - 1))
Finally "OR" the above expressions to get your answer.
I'm trying to do the following:
Write a func setbits(x,p.n,y) that returns x with n bits that begin at
position p set to the rightmost n bits of y,leaving the other bits
unchanged?
I tried it like this but not getting correct answers. Can anyone tell where I am wrong?
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
return (x>>p & (y|(~0<<n)));
}
Something like:
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
unsigned mask = (1U << n) - 1U; // n-bits
y &= mask; // rightmost n bits of y
y <<= p; // which begin at position p
mask <<= p; //idem
x &= ~mask; //set the 0s
x |= y; //set the 1s
return x;
}
Or if you want to do it in fewer lines, more difficult to debug, but waaaay cooler:
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
unsigned mask = (1U << n) - 1U; // n-bits
return (x & ~(mask << p)) | ((y & mask) << p);
}
Kernighan and Ritchie, 2nd edition, exercise 2-6. The solution is from http://users.powernet.co.uk/eton/kandr2/krx206.html :
(x & ((~0 << (p + 1)) | (~(~0 << (p + 1 - n))))) | ((y & ~(~0 << n)) << (p + 1 - n))
You x>>() so you loose x rightmost bits and then never restore them later in you function.
One can not set bits using only & because the result depends on both operands unless you know one of them consists only of 1
(y|(~0<<n)) is supposed to cut bits from y but it's not, this time | is not the right tool, use & and appropriate second operand.
Here is the solution(I bet there is shorter one, but this is straight-forward):
(x & ~(~(~0<<n)<<p) | (y&~(~0<<n)) << p);
Left part of | clears the place in x(n bits at position p) and the right part brings y bits.
Catching the last n bits of y: (will be a number with the last n bits equal to y, and the others set to zero)
last_n_bits_of_y = y & (((1<<(n+1))-1);
then we can offset it by (32-n-p+1) (check this!)
last_n_bits_of_y_offset = last_n_bits_of_y << (32-n-p+1);
now we erase the bits of x we want to change:
new_x = x & (~( (((1<<(n+1))-1) << (32-n-p+1) ) );
and populate it with our bits:
new_x = new_x & last_n_bits_of_y_offset;
That's it! Didn't really test it, but hopefully, you'll get the idea.
I have a function called replaceByte(x,n,c) that is to replace byte n in x with c with the following restrictions:
Bytes numbered from 0 (LSB) to 3 (MSB)
Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
You can assume 0 <= n <= 3 and 0 <= c <= 255
Legal ops: ! ~ & ^ | + << >>
Max ops: 10
int replaceByte(int x, int n, int c) {
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (mask & x) | shift;
}
but when I test it I get this error:
ERROR: Test replaceByte(-2147483648[0x80000000],0[0x0],0[0x0]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000]
after realizing that * is not a legal operator I have finally figured it out...and if you are curious, this is what I did:
int replaceByte(int x, int n, int c) {
int mask = 0xff << (n << 3);
int shift = (c << (n << 3));
return (~mask & x) | shift;
}
Since this looks like homework I'm not going to post code, but list the steps you need to perform:
Cast c into a 32-bit number so you don't lose any bits while shifting
Next, shift c by the appropriate number of bits to the left (if n==0 no shifting, if n==1 shift by 8 etc.)
Create a 32-bit bitmask that will zero the lowest 8 bits of x, then shift this mask by the same amount as the last step
Perform bitwise AND of the shifted bitmask and x to zero out the appropriate bits of x
Perform bitwise OR (or addition) of the shifted c value and x to replace the masked bits of the latter
Ahh... You are almost there.
Just change
return (mask & x) | shift;
to
return (~mask & x) | shift;
The mask should contain all ones except for the region to be masked and not vice versa.
I am using this simple code and it works fine in gcc
#include<stdio.h>
int replaceByte(int x, int n, int c)
{
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (~mask & x) | shift;
}
int main ()
{
printf("%X",replaceByte(0x80000000,0,0));
return 0;
}
Proper solution is for c = 0 as well:
int replaceByte(int x, int n, int c)
{
int shift = 8 * n;
int value = c << shift;
int mask = 0xff << shift;
return (~mask & x) | value;
}
Here is the problem and what I currently have, I just don't understand how it is wrong...
getByte - Extract byte n from word x Bytes numbered from 0 (LSB) to
3 (MSB) Examples: getByte(0x12345678,1) = 0x56 Legal ops: ! ~ &
^ | + << >> Max ops: 6 Rating: 2
int getByte(int x, int n) {
return ((x << (24 - 8 * n)) >> (8 * n));
}
Your shifting doesn't make any sense - first, you shift left by (24 - 8n) bits, then you shift back right by 8n bits. Why? Also, it's wrong. If n is 0, you shift x left by 24 bits and return that value. Try pen and paper to see that this is entirely wrong.
The correct approach would be to do:
int getByte(int x, int n) {
return (x >> 8*n) & 0xFF;
}
Unless i am totally mistaken, your code is mathematically incorrect.
getByte(0x000000ff, 0) {
24 - 8 * n = 24;
8 * n = 0;
0x000000ff << 24 = 0xff000000;
0xff000000 >> 0 = 0xff000000;
return 0xff000000; // should return 0xff
}
Not being allowed to use operators - and especially * is a problem (can't do * 8). I came up with this:
uint8_t getByte (uint32_t x, int n) {
switch (n) {
case 0:
return x & 0xff;
case 1:
return (x >> 8) & 0xff;
case 2:
return (x >> 16) & 0xff;
case 3:
return x >> 24;
}
}
Not exactly beautiful, but it conforms to the problem description: 6 operators, all of them legal.
EDIT: Just had a (pretty obvious) idea for how to avoid * 8
uint8_t getByte (uint32_t x, int n) {
return (x >> (n << 3)) & 0xff;
}
I don't understand how your function works. Try this instead:
int getByte(int x, int n)
{
return (x >> (8 * n)) & 0xFF;
}
Check whether a number x is nonzero using the legal operators except !.
Examples: isNonZero(3) = 1, isNonZero(0) = 0
Legal ops: ~ & ^ | + << >>
Note : Only bitwise operators should be used. if, else, for, etc. cannot be used.
Edit1 : No. of operators should not exceed 10.
Edit2 : Consider size of int to be 4 bytes.
int isNonZero(int x) {
return ???;
}
Using ! this would be trivial , but how do we do it without using ! ?
The logarithmic version of the adamk function:
int isNotZero(unsigned int n){
n |= n >> 16;
n |= n >> 8;
n |= n >> 4;
n |= n >> 2;
n |= n >> 1;
return n & 1;
};
And the fastest one, but in assembly:
xor eax, eax
sub eax, n // carry would be set if the number was not 0
xor eax, eax
adc eax, 0 // eax was 0, and if we had carry, it will became 1
Something similar to assembly version can be written in C, you just have to play with the sign bit and with some differences.
EDIT: here is the fastest version I can think of in C:
1) for negative numbers: if the sign bit is set, the number is not 0.
2) for positive: 0 - n will be negaive, and can be checked as in case 1. I don't see the - in the list of the legal operations, so we'll use ~n + 1 instead.
What we get:
int isNotZero(unsigned int n){ // unsigned is safer for bit operations
return ((n | (~n + 1)) >> 31) & 1;
}
int isNonZero(unsigned x) {
return ~( ~x & ( x + ~0 ) ) >> 31;
}
Assuming int is 32 bits (/* EDIT: this part no longer applies as I changed the parameter type to unsigned */ and that signed shifts behave exactly like unsigned ones).
Why make things complicated ?
int isNonZero(int x) {
return x;
}
It works because the C convention is that every non zero value means true, as isNonZero return an int that's legal.
Some people argued, the isNonZero() function should return 1 for input 3 as showed in the example.
If you are using C++ it's still as easy as before:
int isNonZero(int x) {
return (bool)x;
}
Now the function return 1 if you provide 3.
OK, it does not work with C that miss a proper boolean type.
Now, if you suppose ints are 32 bits and + is allowed:
int isNonZero(int x) {
return ((x|(x+0x7FFFFFFF))>>31)&1;
}
On some architectures you may even avoid the final &1, just by casting x to unsigned (which has a null runtime cost), but that is Undefined Behavior, hence implementation dependant (depends if the target architecture uses signed or logical shift right).
int isNonZero(int x) {
return ((unsigned)(x|(x+0x7FFFFFFF)))>>31;
}
int is_32bit_zero( int x ) {
return 1 ^ (unsigned) ( x + ~0 & ~x ) >> 31;
}
Subtract 1. (~0 generates minus one on a two's complement machine. This is an assumption.)
Select only flipped bit that flipped to one.
Most significant bit only flips as a result of subtracting one if x is zero.
Move most-significant bit to least-significant bit.
I count six operators. I could use 0xFFFFFFFF for five. The cast to unsigned doesn't count on a two's complement machine ;v) .
http://ideone.com/Omobw
Bitwise OR all bits in the number:
int isByteNonZero(int x) {
return ((x >> 7) & 1) |
((x >> 6) & 1) |
((x >> 5) & 1) |
((x >> 4) & 1) |
((x >> 3) & 1) |
((x >> 2) & 1) |
((x >> 1) & 1) |
((x >> 0) & 1);
}
int isNonZero(int x) {
return isByteNonZero( x >> 24 & 0xff ) |
isByteNonZero( x >> 16 & 0xff ) |
isByteNonZero( x >> 8 & 0xff ) |
isByteNonZero( x & 0xff );
}
basically you need to or the bits. For instance, if you know your number is 8 bits wide:
int isNonZero(uint8_t x)
{
int res = 0;
res |= (x >> 0) & 1;
res |= (x >> 1) & 1;
res |= (x >> 2) & 1;
res |= (x >> 3) & 1;
res |= (x >> 4) & 1;
res |= (x >> 5) & 1;
res |= (x >> 6) & 1;
res |= (x >> 7) & 1;
return res;
}
My solution is the following,
int isNonZero(int n)
{
return ~(n == 0) + 2;
}
My solution in C. No comparison operator. Doesn't work with 0x80000000.
#include <stdio.h>
int is_non_zero(int n) {
n &= 0x7FFFFFFF;
n *= 1;
return n;
}
int main(void) {
printf("%d\n", is_non_zero(0));
printf("%d\n", is_non_zero(1));
printf("%d\n", is_non_zero(-1));
return 0;
}
My solution,though not quite related to your question
int isSign(int x)
{
//return 1 if positive,0 if zero,-1 if negative
return (x > 0) - ((x & 0x80000000)==0x80000000)
}
if(x)
printf("non zero")
else
printf("zero")
The following function example should work for you.
bool isNonZero(int x)
{
return (x | 0);
}
This function will return x if it is non-zero, otherwise it will return 0.
int isNonZero(int x)
{
return (x);
}
int isNonZero(int x)
{
if ( x & 0xffffffff)
return 1;
else
return 0;
}
Let assume Int is 4 byte.
It will return 1 if value is non zero
if value is zero then it will return 0.
return ((val & 0xFFFFFFFF) == 0 ? 0:1);