A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘蕴学   /  2012-5-15 20:21  /  6887 人查看  /  34 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

int 型4个字节共32位,左移32位超出界限,左移的时候就用左移的位数减去32,则为x<<(32-32)=x<<o=x
回复 使用道具 举报
其实没有那么复杂
int类型的范围2147483641~-2147483648  
而位移运算就是 m<<n即在数字没有溢出的前提下,对于正数和负数,左移n位都相当于m乘以2的n次方.
除了0之外最小整数是1, 1<<32就等于1*2^32=4294967296 ,已经超出了int的范围了,会出错 ,当n为32时,没有任何意义,所以系统会为n对32取摸

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1 赞一个!

查看全部评分

回复 使用道具 举报
徐然 黑马帝 2012-5-15 23:14:34
23#
System.out.println((7<<0));  结果是7
System.out.println((7<<1));  结果是14
System.out.println((7<<2));  结果是28

System.out.println((7<<32)); 结果是7
System.out.println((7<<33)); 结果是14
System.out.println((7<<34));  结果是28

System.out.println((7<<64));结果是7
System.out.println((7<<65));结果是14
System.out.println((7<<66));结果是28

貌似有点规律了,左移32位相当于7<<0位
而int类型的最小值是-2147483648,也就是10000000000000000000000000000000
而任何int类型值<<31都得到这个数
也就是说int类型的值只要左移32都是没有意义的,就相当于左移0位
超过32的都以大于他的数来计移动位数
那么就以32位作为一个周期,再次回到int的范围


发现的一点小规律,不知道会不会对大家的分析解决这个问题有帮助

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
我要回答这个问题“如果%可以的话,请问为什么位移运算快?”
根据15楼的说法(学习到了,谢谢楼主和15楼及各位)
1、移位运算时计算机可以直接根据左操作数(被移位的数)的类型来取舍右操作数(即要移的位数)的有效低位位数,取舍出来是二进制,可以直接进行移位!
2、用%32(对32取余)时,因为计算机要先对%32进行先运算得到移位的位数,才能进行移位,在这个过程中,计算机多了帮数字“32”申请内存,调用%指令,返回%32结果的时间!所以移位运算要比这个速度更快!

个人的粗浅看法,不知道跟标准答案怎么样?还望赐教!!
回复 使用道具 举报
嘿嘿,,  我个人感觉比较喜欢做这种题目
回复 使用道具 举报
本帖最后由 谢述华 于 2012-5-16 21:30 编辑

上面的兄弟已经讲的很全面了,还是得不到3分,不知是不是和底层有关,某个系统文件用函数的方式定义了位运算的详细步骤。
1、类运行都是由底层的命令实现的,所以我查了下汇编语言的书籍,从中得知汇编程序已经能够实现左移右移命令。
2、我编译了只含有右移命令的,最小的java文件,希望知道右移命令是怎么被执行的。图中可知只引用的Object类。我用反编译工具打开了Object类文件,找不到线索。。
疑点:编译时期java文件就转换为了二进制数据(即进位命令已经执行),Object是如何实现的,是不是通过汇编语言实现的?
自己还在思考中,不过也特别希望得到指点。。。

3333.png (2.49 KB, 下载次数: 31)

3333.png

116.png (50.36 KB, 下载次数: 29)

116.png

Object.rar

640 Bytes, 下载次数: 109

点评

java的表达式是常量表达式5+3 之类的会编译运算,变量表达式是运行期运算  发表于 2012-5-17 00:50
回复 使用道具 举报
看完15楼的终于懂了
回复 使用道具 举报
1<<5应该算是编译运算吧。。。我很想确定<<的具体运算过程 在那个文件可以找到;找不到的话,在那个书里有提及。

点评

think in java  发表于 2012-5-17 05:57
回复 使用道具 举报
看完楼主和15楼的表述,算是大概明白了。
之前一直以为位运算到32是无意义的,全部会为0.
原来java为了避免这种情况,封装了一个&31啊。
回复 使用道具 举报
本帖最后由 jxj4227982333 于 2012-5-24 14:38 编辑

我觉得楼主把问题讲的复杂化了,其实很简单的一个问题吗。
一个数左移32位,比如1<<32;
我们可以这么看的:
1。先把1左移31位就是 1<<31 二进制表示形式就是:1000-0000 0000-0000 0000-0000 0000-0000
2.再把上面那个数再左移一位,但由于它的首位为1,所以把它移出去后补进来的不再是0了而是1,那么得到的结果为
    0000-0000 0000-0000 0000-0000 0000-0001

也就是1咯!
其它的数也是这个道理。
楼主你说呢!{:soso_e112:}

15楼的我也看了下,他说超过32就只取低5位的数,这很好理解,因为32是一个周期,就好像正弦函数一样,不管你在x轴上走了多少个周期,我只想知道你在最后一个周期内在哪里我就可以算出y值了。

点评

我建议你手动试试2左移31位,你看看最低位还是不是1  发表于 2012-5-24 14:32
回复 使用道具 举报
本帖最后由 jxj4227982333 于 2012-5-26 09:42 编辑


刘蕴学  我建议你手动试试2左移31位,你看看最低位还是不是1


楼主你看着啊!
2的二进制表示是              0000-0000 0000-0000 0000-0000 0000-0010
向左移30位就是               1000-0000 0000-0000 0000-0000 0000-0000
再左移一位总共就是31位
由于首位为1所以补1        0000-0000 0000-0000 0000-0000 0000-0001   //这里我错了 是下面这样子的
再左移一位总共就是31位
丢弃最高位1之后就变成了       0000-0000 0000-0000 0000-0000 0000-0000   //修改后的      
再左移一位就共32位了
32%32 =0实际左移0位    0000-0000 0000-0000 0000-0000 0000-0010   =  2
楼主!
回复 使用道具 举报
对于x<<n,当n>=32时等价于 b<<(n%32)
这样做是为了防止我们在一个int数里移动不切实际的位数。超出其存储范围的位移是没有意义的。因为int总共就32位,如果不做处理,左移32位就相当于全部移空了,那么n>32时,结果全部都等于0,这样就完全没有意义。所以Jva内部做了规定,当n>=32时等价于 b<<(n%32),当n=32时就等价于b<<(32%32),也就是b<<0,所以结果不变。
若对byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。只有右侧的5个低位才会用到。long只有右侧的6个低位才会用到,char只有右侧的4个低位才会用到。
回复 使用道具 举报
本帖最后由 jxj4227982333 于 2012-5-26 09:33 编辑

点评
刘蕴学  你自己敲代码移一下吧,这个东西不是这样的  发表于 1 小时前
代码我敲了,跟我的理论是一致的,其实想也想的到,移位超过32之后还有意义吗,没有了!所以超过之后只要取它的低5位就可以了,要不然移位运算比加减乘除还要慢。

int i = 0x40000000; //16进制的40000000,2进制的01000000...0000
i = i << 1;
那么,i在左移1位之后就会变成0x80000000,也就是2进制的100000...0000,符号位被置1,其他位全是0,变成了int类型所能表示的最小值,32位的int这个值是-2147483648,溢出.
如果再接着把i左移1位会出现什么情况呢?C语言中采用了丢弃最高位的处理方法
,丢弃了1之后,i的值变成了0.
以上摘自一篇文章

红字的地方很好的解释了为什么2<<31位后会变成0的。
楼主我并没有否定你的结论,你说的是对的,只是问题似乎并没有你说的那么复杂而已。把1+1=2这样的问题描述的让博士都听的一头雾水就没必要吧,而把爱因斯坦的高深的相对论说的跟小孩子躲猫猫一样浅显易懂这才是深入浅出的最高境界,楼主你说对吧。

回复 使用道具 举报
1、javap可知引用了ishl
  1. 0: bipush 12
  2. 2: istore_1
  3. 3: iload_1
  4. 4: bipush 32
  5. 6: ishl
  6. 7: istore_2
  7. 8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  8. 11: iload_2
  9. 12: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
  10. 15: return
复制代码
2、查询JVM文档可知

JVM文档.png (73.08 KB, 下载次数: 33)

JVM文档.png
回复 使用道具 举报
12
您需要登录后才可以回帖 登录 | 加入黑马