C/C++以及Java中移位的问题以及负数移位

36 篇文章 0 订阅
#include "iostream"
typedef unsigned char byte;
using namespace std;

int main(){
	int x = 0x80000002;//-2的原码,但x不是-2,因为计算机中数值是以补码形式存储的
	cout<<x<<endl;//-2147483646

	int x2 = 0xFFFFFFFE;//-2,说明数值是以补码形式存储的---正数的补码就是本身,负数的补码是正数各位(位数由其类型int\short...决定)取反后加1【负数的补码也可以由负数的原码,符号位不变,其余各位(位数由  决定)取反后加1】,
	cout<<x2<<endl;

	byte x3 = -2;//0xFE
	cout<<(int)x3<<endl;//254,0x000000FE,因为typedef unsigned char byte;所以x3即使等于-2,表示的也是正数

	byte x4 = 0xFE;//-2
	cout<<(int)x4<<endl;//254,0x000000FE

	int x5 = -2;
	x5 >>=2; //x5的补码的基础上移位。右移时,左边以原最高位(正数0,负数1)填充
	cout<<x5<<endl;-1,可知负数移位不是简单的改变2的倍数关系

	int x6 = 4;
	x6 >>=2;
	cout<<x6<<endl;//正数,2的倍数关系

	int x7 = 8;
	x7 >>=32;//对于short、char和int进行移位时,规定实际移动的次数是移动次数和int的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和long位数的余数,也就是移动66次和移动2次得到的结果相同。
	cout<<x7<<endl;


	int x8 = 8;
	x8 <<=32;
	cout<<x8<<endl;

	cout<<sizeof(short)<<endl;//2
	short x9 = 8;
	x9 <<=32;
	cout<<x9<<endl;

      short x10 = 0xFFFE;
      cout<<x10<<endl;//-2
      x10 >>=2;
     cout<<x10<<endl;
     return 0;
}
/**
 * 在计算机系统中,数值一律用补码来表示(存储)。 主要原因:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补 码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。 2、补码与原码的转换过程几乎是相同的。
 * 
 * 计算机中的符号数有三种表示方法,即原码、反码和补码。它们均由符号位和数值部分组成,符号位的表示方法相同,都是用1表示“负”,用0表示“正”。
 * 
 * 在移位运算时,byte、short和char类型移位后的结果会变成int类型,对于byte、short、char和int进行移位时,规定实际移动的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是移动66次和移动2次得到的结果相同。
 * 所有的整数类型(除了char 类型之外)都是有符号的整数。这意味着他们既能表示正数,又能表示负数。Java 使用大家知道的2的补码(two’s complement )这种编码来表示负数,也就是通过将与其对应的正数的二进制代码取反(即将1变成0,将0变成1),然后对其结果加1。
 * 1: 0000 0000 0000 0000 0000 0000 0000 0001
 * -1:源码1000 0000 0000 0000 0000 0000 0000 0001;补码:1111 1111 1111 1111 1111 1111 1111 1111
 * 
 * 负数的补码等于其绝对值的原码各位取反,然后整个数加1的数值。
 * 
同一个数字在不同的补码表示形式里头,是不同的。比方说-15的补码,在8位2进制里头是11110001,然而在16位2进制补码表示的情况下,就成了1111111111110001。在这篇补码概述里头涉及的补码转换默认把一个数转换成8位2进制的补码形式,每一种补码表示形式都只能表示有限的数字。
【例2】求-7的补码。
因为给定数是负数,则符号位为“1”。
后七位:-7的原码(10000111)→按位取反(11111000)(负数符号位不变)→加1(11111001)
所以-7的补码是11111001。
注:数0的补码表示是唯一的:
+0的补码=+0的反码=+0的原码=00000000
-0的补码=11111111+1=00000000(mod 2的8次方)


 */

/**
 * @author yutian
 *
 */
import java.util.*;
public class Test5_5 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 byte k = -2 ; //
		 System.out.println(k+"的二进制是:"+Integer.toBinaryString(k));
		 /**
		 * 得到-2的二进制是:11111111111111111111111111111110(补码)
		 * 由于java 中负数采用补码的方式表示,转成实际的原码应该是
		 * 符号位不变,各位取反+1
		 * 也即是
		 * 11111111111111111111111111111110的原码是
		 * 100000000000000000000000000000010
		 */
		 k >>= 2 ;//补码的基础上移位,右移是,左边以最高位填充
		 
		 /**
		 *根据补码理解:11111111111111111111111111111110
		 *得到k 向右移2位,移空位补1
		 *应该得到的值 11111111111111111111111111111111(补码),
		 *实际的值是: 100000000000000000000000000000001  (-1)
		 */
		 System.out.println(k);//-1,可知负数移位不是简单的改变2的倍数关系
		 
		 byte k2 = 4 ;
		 k2 >>= 2 ;
		 System.out.println(k2);//正数,2的倍数关系
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值