Сделайте арифметическое смещение влево на x на n бит (C) - PullRequest
0 голосов
/ 02 октября 2019

Я и моя группа из 4 человек совершенно не понимаем, как правильно сделать арифметическое смещение влево целого числа x на величину n битов.

Это проблема из-за домашних заданий по манипулированию битами для C. Нам не разрешено использовать циклы, операторы if или любые операции старше 15. Я прикрепил код, приведенный ниже. Кроме того, простое решение x << n не работает, хотя я уверен, что мы упускаем что-то очевидное. Если кто-то может помочь или предоставить руководство, оно будет очень признательно. </p>

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

Текущее сообщение об ошибке:

Test arithLeftShift(-2147483648[0x80000000],1[0x1]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000

Ответы [ 3 ]

0 голосов
/ 02 октября 2019

На самом деле, это не арифметическое смещение влево. Это ваш arithLeftShift с вашим знаковым битом, который не требует левого смещения. И старшие биты нужно было сдвинуть в младшую позицию, это похоже на циклический сдвиг.

#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);
    }
}
0 голосов
/ 02 октября 2019

Ваш запрос, по-видимому, состоит в том, чтобы «повернуть» целое число «Влево», «n» количество раз, но сохранить «бит знака» (MSB), если установлено.

Одно из решений будет ... ...

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

}

Объяснение:

  • (x << n) </li>

Сдвиг влево x, n раз - последние n битовноль.

(x >> (INT_BITS - n) & ~ (~ 0 << n)) </p>

Сдвиг вправо x (INT_BITS - n) раз для установки первых n битов висправьте положение и введите «И» с помощью ~ (~ 0 << n), чтобы установить верхние биты в ноль. Это позаботится о «расширении знака», если оно есть. </p>

(x << n | (x >> (INT_BITS - n) & ~ (~ 0 << n))) </p>

«ИЛИ» для выполнения операции «Повернуть влево».

  • x & (~ 0 << (INT_BITS - 1) </li>

Сдвиг влево «-1», 31 раз и «И» с помощью x, чтобы проверить, установлено ли значение MSB для x.

(x << n | (x >> (INT_BITS - n) & ~ (~ 0 << n))) | x & (~ 0 << (INT_BITS - 1)) </p>

Наконец "ИЛИ"Приведенные выше выражения, чтобы получить ваш ответ.

0 голосов
/ 02 октября 2019

Вам нужно сдвинуть биты без потери знака, потому что целочисленное представление находится в дополнении к двум.

...