位操作问题,急求大神!!
编写一个函数rightrot(x, n),该函数返回将x循环右移(即从最右端移出的位将从最左端移入)n(二进制)位后所得到的值。这个函数的两种形式我认为是等价的
但是实验告诉我,不等价
谁能告诉我为什么第二种错了
第一种
int rightrot(unsigned int x , int n)
{
int k,i,m;
int ribits;
k = x;
for ( i = 0; k!=0; i++)
{
k=k>>1;
}
ribits = (~(~0<<n) & x)<<(i-n);
x = (x>>n) | ribits;
return x;
}
第二种
int rightrot(unsigned int x , int n)
{
int k,i,m;
int ribits;
k = x;
for ( i = 0; k!=0; i++)
{
k=k>>1;
}
ribits = ((~0<<n) | x)<<(i-n);
x = (x>>n) | ribits;
return x;
}
设x=122(二进制:1111010)
设n=3
ribits = ((~0<<n) | x)<<(i-n);
~0: 1111111
~0<<n:1111000
~0<<n | x: 1111010
(~0<<n | x)<<(i-n):0100000
设x=122(二进制:1111010)
设n=3
ribits = (~(~0<<n) & x)<<(i-n);
~0:1111111
~0<<n;1111000
~(~0<<n): 0000111
~(~0<<n)& x:0000010
(~(~0<<n)& x)<<(i-n): 0100000
我完全看不懂你在做什么,能解释一下这个代码的逻辑吗?
就是循环右移么,不用这么费劲呀
#include <stdio.h>
#include <stdint.h>
uint32_t rightrot(uint32_t x, uint32_t n) {
for(int i = 0; i < n; ++i) {
x = (x >> 1) | (x & 0x01 ? 0x80000000 : 0);
}
return x;
}
int main(void) {
printf("%x\n", rightrot(123, 3));
return 0;
}
你的思路是什么样的?
你打算怎样完成这个右移?
#include <stdio.h>
#include <stdint.h>
int rightrot(unsigned int x , int n)
{
int k,i,m;
int ribits;
k = x;
for ( i = 0; k!=0; i++)
{
k=k>>1;
}
ribits = (~(~0<<n) & x)<<(i-n);
x = (x>>n) | ribits;
return x;
}
int main(void) {
printf("%x\n", rightrot(123, 3));
return 0;
}
$ ./main.exe
3f
你认为这两个,哪一个是对的?
#include <stdio.h>
#include <stdint.h>
int rightrot(unsigned int x , int n)
{
int k,i,m;
int ribits;
k = x;
for ( i = 0; k!=0; i++)
{
k=k>>1;
}
ribits = ((~0<<n) | x)<<(i-n);
x = (x>>n) | ribits;
return x;
}
int main(void) {
printf("%x\n", rightrot(123, 3));
return 0;
}
$ ./main.exe
ffffffbf 人造人 发表于 2020-5-14 23:45
你的思路是什么样的?
你打算怎样完成这个右移?
我第一个for循环是计算出计算机中的二进制有多少位
之后把x的最右端的三位截取下来,之后x右移n位
再把截取下来的不到x最左端 人造人 发表于 2020-5-14 23:53
你认为这两个,哪一个是对的?
第一种是对的,最后输出十进制
比如输入111输出125
人造人 发表于 2020-5-14 23:44
我完全看不懂你在做什么,能解释一下这个代码的逻辑吗?
就是循环右移么,不用这么费劲呀
0x01 ? 0x80000000 : 0
这一句看不懂 JerryLeeSir 发表于 2020-5-14 23:57
0x01 ? 0x80000000 : 0
这一句看不懂
就是把最低位补到最高位
人造人 发表于 2020-5-15 00:01
就是把最低位补到最高位
0x01是什么
0x80000000也不知道是啥 我觉得你理解错了,循环位移不是这样的
循环位移需要先规定一个宽度,是8位运算、是16位运算还是32位运算?或者是64位运算?
123循环右移3位
8位的
01111011
01101111
16位的
00000000 01111011
01100000 00001111
32位
00000000 00000000 00000000 01111011
01100000 00000000 00000000 00001111
就是把最低位补到最高位 人造人 发表于 2020-5-15 00:11
我觉得你理解错了,循环位移不是这样的
循环位移需要先规定一个宽度,是8位运算、是16位运算还是32位运算 ...
c程序设计语言第二版,答案思路就是不知道多少位,要自己算位数 JerryLeeSir 发表于 2020-5-15 00:06
0x01是什么
0x80000000也不知道是啥
x = (x >> 1) | (x & 0x01 ? 0x80000000 : 0);
x & 0x01 就是
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
&
00000000 00000000 00000000 00000000
=
00000000 00000000 00000000 0000000?
就是看最低位是0还是1
如果是1那就
x = (x >> 1) | 0x80000000;
就是or上
10000000 00000000 00000000 00000000
0x80000000就是最高位为1
如果是0,那就or上0,结果就是和没有or一样
JerryLeeSir 发表于 2020-5-15 00:14
c程序设计语言第二版,答案思路就是不知道多少位,要自己算位数
好吧,但是在实际应用中绝对不是这样做的
是事先规定运算位数
ribits = ((~0<<n) | x)<<(i-n);
这个的问题就和我上面说的一样,因为x是32位的
(~0<<n) | x
这个左移不会帮你把超过7位的1丢掉,前面的那一堆的1依然保留着
如果你要这么做,你就必须自己把前面多余的1全部去掉,32位运算可以保留前面的那一堆1
JerryLeeSir 发表于 2020-5-15 00:14
c程序设计语言第二版,答案思路就是不知道多少位,要自己算位数
不知道多少位……难道要 sizeof 一下吗……
页:
[1]