x循环右移n位

i945800687 2011-11-23 12:31:16

/*
编写一个函数rightrot(x, n),该函数返回将x循环右移(即从
最右端移出的位将从最左端再移入)n(二进制)位后得到的值
*/

#include <stdio.h>

int wordlength();
unsigned rightrot(unsigned x, int n);

int main()
{
int x, n;
int a;

x = 32769;
n = 7;

a = rightrot(x, n);

printf("a = %d\n", a); // 33554688

return 0;
}

// 计算运行该程序的计算机字长
int wordlength()
{
int i;
unsigned v;

v = (unsigned)~0;

for (i = 1; (v=v>>1) > 0; ++i)
{
;
}

return i;
}

/*
如果对x进行循环右移的总位数(n)与一个无符号整数的二进制
位数(即这台计算机的字长)相等,完成这些次循环右移后的结
果将与x完全一样,因此我们就不必对x进行循环右移了。
如果n小于这台计算机的字长,那我们就必须把x循环右移n位。
如果n大于这台计算机的字长,那么,我们只需先(利用取模运
算符)求出n对这台计算机的字长的余数,再把x循环右移这个余
数所代表的次数。基于上述分析,我们将得到一个不需要使用循
环语句的解决方案。

~0 << n,把一个全1的屏蔽码左移n位,在它的最右端制造出n位0
~(~0 << n),把屏蔽码最右端的n位设置为1,其余位则设置为0

当我们用这个屏蔽码和x进行AND运算时,x最右端的n位将被赋值
给变量rbits。然后,将rbits中的1左移到它的最左端,把x右移
n位,再对右移后的x和rbits进行OR运算,就完成了对无符号整
数x循环右移n位
*/

unsigned rightrot(unsigned x, int n)
{
unsigned rbits;

if ((n=n%wordlength()) > 0)
{
rbits = x & ~(~0<<n);
rbits = rbits << (wordlength()-n);
x = x >> n;
x = x | rbits;
}

return x;
}



问题一:
main函数里面我把x定义的是int型,但是函数声明里是unsigned型
二种类型我都试着定义过,答案都一样
一个int,一个unsigned,我也试过,答案也一样
可我记得书上讲过,“函数实参和形参类型必须相同”
这里2种却都能行得通
之前做过的2道题拿来试验也是一样的
可这样对程序准确性有没有影响呢?



问题二:
rightrot函数里面这句“rbits = rbits << (wordlength()-n);”
我直接写成“rbits << (wordlength()-n);”可以吗?
...全文
838 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
i945800687 2011-11-30
  • 打赏
  • 举报
回复
-12 -13

谨记
selooloo 2011-11-30
  • 打赏
  • 举报
回复
“为了保证位运算准确性”,其实可以说看你需要什么样的结果,有符号数会在左面补1,无符号数补0
你的分析是对的
selooloo 2011-11-30
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 i945800687 的回复:]
-9 神人!


请看我的分析过程对不:

1. a右移1位后,执行程序 a = 2147483647
二进制:1111 1111 1111 1111 1111 1111 1111 111 (31位)

2. 第一步,a = -1,在计算机运算中转换成补码如下:
(1) 1 0000 0000 0000 0000 0000 0000 0000 0001 (33位,最左端1为符号位……
[/Quote]
其实和低层关系不大,但位移比一般的运算接近低层点,效率也高些

我学C用了1年多,相信你可以超过我的
赵4老师 2011-11-25
  • 打赏
  • 举报
回复
有现成的循环右移汇编指令ROR不用白不用!
i945800687 2011-11-25
  • 打赏
  • 举报
回复
-9 神人!


请看我的分析过程对不:

1. a右移1位后,执行程序 a = 2147483647
二进制:1111 1111 1111 1111 1111 1111 1111 111 (31位)

2. 第一步,a = -1,在计算机运算中转换成补码如下:
(1) 1 0000 0000 0000 0000 0000 0000 0000 0001 (33位,最左端1为符号位)
(2) 取反:1111 1111 1111 1111 1111 1111 1111 1110
(3) +1:1111 1111 1111 1111 1111 1111 1111 1111

3.第二步,a >> 1,即程序输出结果:
1111 1111 1111 1111 1111 1111 1111 111 (31位)


由此说来,为了保证位运算准确性似乎是必须使用unsigned型的
另请教:
1. 这类研究算或者接近底层吗
2. 到你这样的水平大概要多久,我从开始学C到发这个帖子刚好10个月,平均每天有3个小时
i945800687 2011-11-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pathuang68 的回复:]
用-1传进去试试。
[/Quote]

用-1还是一样

另外补充:函数声明里面的x必须定义为unsigned,不然报错
pathuang68 2011-11-23
  • 打赏
  • 举报
回复
用-1传进去试试。
selooloo 2011-11-23
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 i945800687 的回复:]
书上有句话:

将x声明为无符号类型是为了保证将x右移时,无论该程序在什么机器上运行,左边空出的位都用0(而不是符号位)填补

能不能用这句话去理解问题一呢,具体怎么解释呢?
[/Quote]
用这个代码试下

#include <stdio.h>

int main(void)
{
unsigned int a=-1;
int b=-1;

printf("%d %x\n",a,a);
a>>=1;
printf("%d %x\n",a,a);

printf("%d %x\n",b,b);
b>>=1;
printf("%d %x\n",b,b);

getchar();
return 0;
}




问题二

rbits = rbits << (wordlength()-n);”
这样会修改rbits值
i945800687 2011-11-23
  • 打赏
  • 举报
回复
书上有句话:

将x声明为无符号类型是为了保证将x右移时,无论该程序在什么机器上运行,左边空出的位都用0(而不是符号位)填补

能不能用这句话去理解问题一呢,具体怎么解释呢?

i945800687 2011-11-23
  • 打赏
  • 举报
回复
-4 C函数不存在重载 是什么意思哦,不懂~~~

-5 赵哥的代码看不懂,能解释下吗?

-6 谢谢,知道了
薛定谔之死猫 2011-11-23
  • 打赏
  • 举报
回复
第二个问题看错了,你必须保存运算结果

rbits <<= (wordlength()-n);
赵4老师 2011-11-23
  • 打赏
  • 举报
回复
unsigned rightrot(unsigned x, int n){
__asm {
mov eax,x
ror eax,n
}
}

薛定谔之死猫 2011-11-23
  • 打赏
  • 举报
回复
问题一、C函数不存在重载,因此调用时会进行隐式类型转换,这在C各种语言中是最常见不过的事情;
问题二、从C语言运算符的优先级看,右移运算符优先级比减法运算符低,因此去除括号是没什么分别的。
i945800687 2011-11-23
  • 打赏
  • 举报
回复
吃顿饭回来发现了一个问题

unsigned似乎是专门用来区分int的

平时我们输入int就是默认的signed型,加了unsigned就是无符号的


那上面那种程序会不会是这样的情况:
1. 函数声明类型是unsigned
2.其中有个wordlength函数是计算计算机字长的(现在一般都是32位)
这句“v = (unsigned)~0;”不就默认了范围是32位而且还是无符号的
3.既然函数限制了是无符号的,那么在main里面x被定义为int或者unsigned是不是就都能实现同种效果,因为限制范围32位都是正的

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧