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.
Related
I am trying to come up with a function int rotateRight (int x, int n) that rotates x to the right by n. For example,
rotateRight(0x87654321,4) = 0x76543218
This is what I have so far:
int rotateRight(int x, int n) {
int mask = (((1 << n)-1)<<(32-n));
int reserve = (int)((unsigned) (x&mask) >>(32-n));
return (x << n) | reserve;
}
However, I am forbidden to use any casting, and the allowed operations are ~ & ^ | + << and >>. Can anyone help me fix this?
Basically all you have to do is:
shift everything right by n bits using right shift: >>
shift the bits you want to rotate all the way to the left: <<
Combine the shifted right and shifted left bits with or: |
See this code for an example implementation using the function signature you require:
int rotateRight(int x, int n) {
//if n=4, x=0x12345678:
//shifted = 0x12345678 >> 4 = 0x01234567
int shifted = x >> n;
//rot_bits = (0x12345678 << 28) = 0x80000000
int rot_bits = x << (32-n);
//combined = 0x80000000 | 0x01234567 = 0x81234567
int combined = shifted | rot_bits;
return combined;
}
This implementation isn't safe though, at least not without a few guarantees - namely that x will always be positive, and n will be positive and always <= 32.
If you pass in a negative integer for shifting, it will work incorrectly since it will sign-extend the left-most bit. If you want this function to work for all integers, you should change all the types from int to unsigned int (that way no sign-extension or negative left-shifting will take place) and then modulo n by 32 (% 32). Here is a safe version of the function:
unsigned int rotateRight(unsigned int x, unsigned int n) {
//needed so you don't right shift more than int width
n %= 32;
//needed so you don't left shift more than int width
unsigned int leftshift_val = (32-n) % 32
unsigned int shifted = x >> n;
unsigned int rot_bits = x << leftshift_val;
unsigned int combined = shifted | rot_bits;
return combined;
}
And golfed down to a single line, for you minimalists:
unsigned rotr(unsigned x, unsigned n) {
return (x >> n % 32) | (x << (32-n) % 32);
}
A rotation is done with a combination of left and right shifts.
Shifting a signed integer's sign bit is a problem. Suggest converting to unsigned to perform the shift. #The Paramagnetic Croissant
An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.
Shifting by the bit width or more is a problem. Limit actual shifting to n modulo Bit_width. OP's (...<<(32-n)); code is a problem when n == 0.
OP's example looks more like a left rotate. Will assume the function should rotate right. (0x87654321,4) --> 0x18765432. #Mark Shevchenko
An int may have a width other than 32.
#include <limits.h>
#define INT_BIT_WIDTH (sizeof (int) * CHAR_BIT)
int rotateRight(int x, int n) {
unsigned xu = x;
unsigned nu = n;
nu %= INT_BIT_WIDTH;
unsigned y = xu >> nu;
if (nu > 0) {
y |= xu << (INT_BIT_WIDTH - nu);
}
return y;
}
[Edit] as OP is limited to ~ & ^ | + << >>, use the alternate following code.
Note: This is an issue in rare cases where the width of an int is not a power of 2.
// nu %= INT_BIT_WIDTH;
nu &= INT_BIT_WIDTH - 1;
[Edit2] Thought I would form an unsigned minimalistic solution as inspired by #RPGillespie as OP cannot use %.
#include <limits.h>
#define UNS_WIDTH (sizeof (unsigned) * CHAR_BIT)
#define UNS_WIDTH_M1 (UNS_WIDTH - 1)
unsigned unsigned_rotate_right(unsigned x, unsigned n) {
return (x >> (n & UNS_WIDTH_M1)) | (x << ((UNS_WIDTH - n) & UNS_WIDTH_M1));
}
According to this explanation, rotation can be done with the following implementation.
#include<stdio.h>
#define INT_BITS 32
/*Function to left rotate n by d bits*/
int leftRotate(int n, unsigned int d)
{
/* In n<<d, last d bits are 0. To put first 3 bits of n at
last, do bitwise or of n<<d with n >>(INT_BITS - d) */
return (n << d)|(n >> (INT_BITS - d));
}
I had a problem in hand as this :
"Exercise 2-6. Write a function setbits(x,p,n,y) that returns x with the n bits that begin at
position p set to the rightmost n bits of y, leaving the other bits unchanged."
I've written a function for this as below. This is working as expected.
int func_setx(int x,int p,int n,int y)
{
int a_t= ~0 << (p+n);
int b_t= ~a_t >> n;
int x_t= x& (a_t | b_t); // a temporary x which has the bits to be changed as 0 , rest of the bits unchanged.
int mask= (y << p) & (~(~0 << (p+n))); // a mask which has required bits from y in positions to be set , rest all bits 0.
printf("\nCheckpoint : mask= %x x_t= %x\n",mask,x_t);
int result= mask|x_t;
return result;
}
But I somehow feel the logic is long and can be optimized, but can't think of any other way yet.
Can anyone suggest any optimization to this please?
To make an n bit mask:
mask_y = (1U << n) - 1;
To start it at bit p:
mask_x = mask_y << p;
Clear the appropriate bits in x:
x &= ~mask_x;
Extract the bits from y:
y &= mask_y;
Upshift them to position p:
y <<= p;
Put it all together:
result = x | y;
Or in a more compact form:
mask = (1U << n) - 1;
result = x & ~(mask << p);
result |= (y & mask) << p;
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.
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;
}
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