精华内容
下载资源
问答
  • 有符号位数的运算

    千次阅读 2018-03-02 17:41:15
    无符号数:最高位不用来表示正负,它没有负数,比如,4位无符号数表示范围,0000-1111,大小即0-15,有符号数:最高位用来表示正负原码反码补码 0正1负数 最高位永远是符号位 当二进制为正数时,原码、反码、...

    无符号数:最高位不用来表示正负,它没有负数,比如,4位无符号数表示的范围,0000-1111,大小即0-15,

    有符号数:最高位用来表示正负

    原码反码补码

        0正1负数 最高位永远是符号位

        当二进制为正数时,原码、反码、补码相同

        当二进制为负数时,反码=原码的数值位逐一取反,补码=反码在最低位加1

    数值在计算机的表示都是用补码来表示的,所以计算机的加减法都是补码的加减法,比如

     [+1] = [00000001]原 = [00000001]反 = [00000001]补

     [-1] = [10000001]原 = [11111110]反 = [11111111]补


    1000 0000=-128     0000 0000=0      1111 1111=127

     (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补


    int4个字节  每个字节8位  共32位 Integer是有符号的
    Integer.MAX_VALUE 01111111 11111111 11111111 11111111 = 2^31-1 = 2147483647 21亿   0x7fffffff
    Integer.MIN_VALUE 10000000 00000000 00000000 00000000 = -2^31 = -2147483648 -21亿  0x80000000


    System.out.println(Integer.MAX_VALUE);     2147483647
    System.out.println(Integer.MAX_VALUE + 1); -2147483648
    System.out.println(Integer.MIN_VALUE);     -2147483648
    System.out.println(Integer.MIN_VALUE - 1); 2147483647


    这是一个困惑了我几年的问题,它让我对现在的教科书和老师极其不满,从我N年前开始摸电脑时,就几乎在每一本C++教科书上都说,8位有符号的取值范围是-128~+127,为什么不是-127~+127呢,后来的java,int的聚值范围,再32位计算,-2^31 ~ +2^31-1,可是,却从来没有任何一本教科书或一个老师比我解释过这个问题。 原因没有在工作上或者是什么地方直接遇到它,所以我也一直忽略它,但心里总是有一根刺.直到刚才!!!!

    就是刚才,无聊之极,在看汇编的书时,又遇到它了,但一如以往,书上直接地,有心地,明显地绕过了这个问题,真是可恶啊.     几经周折,终于把它搞清楚了: 
    其实,它是计算机底层为了实现数值运算而决定的,涉及非常非常基础的原码,反码,补码知识,一般(99.9999%)都不会用得上. 那0.0001%,估计也就是计算机考试了. 
        话说: 
        用2^8来表示无符号整数的话,全世界的理解都是0 - 255了,那么,有符号呢? 用最高位表示符号,0为+,1为-,那么,正常的理解就是 -127 至 +127 了. 
        这就是原码了,值得一提的是,原码的弱点,有2个0,即+0和-0,还有就是,进行异号相加或同号相减时,比较笨蛋,先要判断2个数的绝对值大小,然后进行加减操作,最后运算结果的符号还要与大的符号相同. 
    于是乎,反码产生了,原因....略,反正,没过多久,反码就成为了过滤产物,也就是,后来补码出现了. 
         补码的知识不说述,只说有关+127和-128的. 
         官方的定义 [-2^(n-1),2(n-1)-1],补码的0没有正负之分.原因呢?没有一本书上有说,这也是我这么火的原因,但通过思考,google,再思考,很快找到答案:      首先,难不免干点白痴般地事情,穷举一下... 正数,原码跟补码一样 

    +127, 0111 1111 

    +126, 0111 1110 

    +125, 0111 1101 

    +124, 0111 1100 

    +123, 0111 1011 

    +122, 0111 1010 ... 
      +4, 0000 0100  

     +3, 0000 0011   

    +2, 0000 0010   

    +1, 0000 0001 
       0, 0000 0000 (无正负之分)  
    下面是负数了,值,原码,符号位不变其它取反,+1   

    -1, 1000 0001, 1111 1110, 1111 1111 
    -2, 1000 0010, 1111 1101, 1111 1110   

    -3, 1000 0011, 1111 1100, 1111 1101   

    -4, 1000 0100, 1111 1011, 1111 1100   

    -5, 1000 0101, 1111 1010, 1111 1011   

    -6, 1000 0110, 1111 1001, 1111 1010   

    -7, 1000 0111, 1111 1000, 1111 1001   

    -8, 1000 1000, 1111 0111, 1111 1000   

    -9, 1000 1001, 1111 0110, 1111 0111 

    -10, 1000 1010, 1111 0101, 1111 0110 

    -11, 1000 1011, 1111 0100, 1111 0101 

    -12, 1000 1100, 1111 0011, 1111 0100 

    -13, 1000 1101, 1111 0010, 1111 0011 

    -14, 1000 1110, 1111 0001, 1111 0010 

    -15, 1000 1111, 1111 0000, 1111 0001 

    -16, 1001 0000, 1110 1111, 1111 0000 

    -17, 1001 0001, 1110 1110, 1110 1111 ... 

    -24, 1001 1000, 1110 0111, 1110 1000 ... 
    -99, 1110 0011, 1001 1100, 1110 0100 ... 
    -124, 1111 1100, 1000 0011, 1000 0100 

    -125, 1111 1101, 1000 0010, 1000 0011 

    -126, 1111 1110, 1000 0001, 1000 0010 

    -127, 1111 1111, 1000 0000, 1000 0001 

    看出点什么了没有? 
    如果没有,那么,给个提示, 再继续下去,下一个补码是什么呢? 

    当然是 

    -128, 先略过,再略过, 

    1000 0000 1000 0000,那么,它的原码是什么呢? 
    从补码求原码的方法跟原码求补码是一样的 
    先保留符号位其它求反:  1111 1111, 再加1:11000 0000, 超过了8位了 

    对,用8位数的原码在这里已经无法表示了 
    关键就在这里,补码 1000 0000 为 -128 是不用怀疑的(上面的穷举),

     那么,回到原码处, 它的原码也是 1000 0000(超出的自动丢失), 

    1000 0000 在原码表示什么呢? -0, 但补码却规定0没有正负之分

     转换一下思路,看看计算机里,是怎么运算的: 

    对于负数,先取绝对值,然后求反,加一 
    -128 -> 128 -> 1000 0000 -> 0111 1111 -> 1000 0000 

    现在明确了吧. 
    所以, 8位有符号的整数取值范围的补码表示 

    1000 0000 到 0000 0000, 再到 0111 1111 

    即 -128 到 0, 再到 127 

    最终 -128 ~ +127

    展开全文
  • Verilog无符号数和有符号数的运算
  • 有符号数的运算方法

    千次阅读 2020-05-12 20:35:37
    一.有符号数的加减法 1、符号数与无符号数的人为规定性: 一个数,是有符号数还是无符号数都是人为规定的。进行二进制运算时用无符号数或是补码运算时,结果都...机器中的有符号数的运算一般就是补码的运算。 2、补

    一.有符号数的加减法

    1、符号数与无符号数的人为规定性:

    一个数,是有符号数还是无符号数都是人为规定的。进行二进制运算时用无符号数或是补码运算时,结果都是正确的。

    10000100+00001110

    若规定为无符号数,即 132+146=146D 。

    若规定为符号数,则为-124+14=-110,而[-110]补=10010010。解释:10000100是 -124的补码,0001110是14的补码,在机器中运算后得出的结果是[-110]的补码。机器中的有符号数的运算一般就是补码的运算。

    2、补码加减法运算

      计算机中,当确定为符号数运算时,符号数一律用补码表示,运算时符号位和数字位一起参加运算。同样,运算结果也用补码表示。

    1)两符号数相加公式:

    [X+Y]补 (MOD2)=[X]补+[Y]补    //MOD2即 mod 2^n,即丢弃符号位的进位(因为符号位参与运算是补码运算的特点)

    2)两符号数相减公式:

    [X-Y]补 (MOD2)= [X]补+[-Y]补

     

    3.例子:

    求3CH-90H。

    首先3CH=0011 1100,90H=1001 0000

    (1)当为有符号数时,显然这两个数是某两个数的补码。(具体是哪两个数X Y, 需要自己计算)。运算结果也是补码,是X-Y的补码 [X-Y]补。机器只运算到这一步。[X-Y]补 就是运算结果,溢出 进位等标志位也都是这个补码运算过程的结果,由硬件ALU运算。X-Y并不是机器的运算结果,由[X-Y]补求X-Y是在计算机组成原理中由程序员或者编译器完成的工作,对于编译器来说运算结果才是X-Y,编译器属于软件,不属于硬件机器。

     

    根据微机中有符号数(补码)的减法公式,[x]补(输入)-[Y]补(输入)=[x]补+[-Y]补(求补操作结果)=[X-Y]补(微机运算结果) ,求[-Y]补是关键

    [x]补=0011 1100,[Y]补=1001 0000,

    [-Y]补=[Y]补的 求补=0110 1111(取反)+1(加一)=0111 0000  //不是[Y]补的补码!!更不存在什么 -[Y]补 的补码(不存在-[Y]补这种写法)

     解释求补操作:  

    无论-[Y]补的符号位是0还是1。正数也可以有求补操作,只是得到的数不叫补码,就是为了把减法转换成加法。求补操作 就是取余(求补)(补码是人规定的,但是求补是数学定义)。证明[-Y]补=对-[Y]补 求补操作:[0]补=[-x]补+[X]补 。[-x]补和[X]补不是正数和负数的关系!!而是互补关系,算数相反,不是逻辑相反。另外仔细想一下,我们学补码是为了什么?以前是为了求一个原码的补码是什么,因为计算机组成原理中 从编译器到微机 从微机到编译器 需要原码变成补码 补码变成原码,但是在微机原理中,就不需要这一部分了,而是需要 求补操作了。计算机组成原理中,是由y原码求出来的[-y]补,而微机原理中是 对[y]补 求反操作出来的[-y]补,计算过程都不一样。计算机组成原理中的过程可以理解 但是不是微机真正的运算过程,这一次学习的微机原理的补码的加减法才是真的硬件的运算过程!

    另外,补充一点,X=[X]补 的补码,由补码求原码时不用按照由原码求补码的逆过程(补码为1000 0000时例外!)。

    《微机原理与接口技术》中写道:“由加法器的原理图,加法器的方式控制M用于控制加减法,当M=0时进行S=A+B操作,当M=1时进行S=A-B操作。当M=1(减法)时,各个异或门对B的各位进行求反,并将1作为初试进位加入结果,也就是执行对B的求反加1,即求补操作。” 也就是说!无论B是有符号数还是无符号数,无论符号位是0还是1,只要M=1,就统统对B执行求补操作!!!所以,求补操作可以对符号位是0的数执行!

     

    所以,[X-Y]补=0011 1100-1001 0000=0011 1100+0111 0000=ACH

     

    (2)补码最大好处就是不管是有符号数还是无符号数都可以用同一套加减法。系统对有符号数和无符号数的加减法都采用一样的策略。

    无符号加减法不存在溢出问题,只是将进位或借位存储在CF中。
    机器不知道你进行的运算是否有符号,如果你进行的是有符号运算,你需要查看OF,否则不需要。
    所以,溢出不溢出,是由程序员判断的,机器不知道。

     

    不管是有符号数还是无符号数,微机都是按补码运算,至于是进位还是溢出不仅要看进位标志位,还要看溢出标志位。

    只不过在做无符号数运算时程序员不考虑溢出标志位,只考虑进位标志位而已。
    比如0111+1101,你说它是无符号数7+13呢,还是有符号数7-3呢?
    对微机而言这是一回事!

    所以,微机中,无符号数时和有符号数时的运算结果一定是一样的。

     

    (3)注意这道题和《计算机组成原理》学补码加减运算时的题目的区别。

    例子:X=+0101,Y=-1010,求X-Y。

    题目给的X Y,是原码, 所以已经默认是有符号数,也有判断是否溢出,所以默认的计算过程也是指机器运算过程。

    原码在机器中 均是以补码保存和运算的,

    [x]补-[Y]补=[x]补+[-Y]补=[X-Y]补,只用到了[x]补+[-Y]补=[X-Y]补

    属于类型:已知X Y,所以先求[X]补, [-Y]补 ,便求得[X-Y]补。然后求X-Y。

    也就是说,上一题已知的是[X]补 [Y]补,(机器的)运算结果是[X-Y]补。中间过程没必要求出X Y是什么数。

    本题已知的是X Y,先得出机器的运算结果[X-Y]补,在做编译器的工作由[X-Y]补 求出X-Y。

    二者求[-Y]补的方法不一样:前者是对[Y]补 求补操作 求得的,后者是由-Y求得。

    可以说,后面例子是编译器和微机共同工作的过程,前面例子只关系微机运算。

    展开全文
  • C语言无符号数与有符号数的运算原则,一些容易踩坑的点
    int main(void)
    {
    	for (int i = -1; i < sizeof(int); i++) {
    		printf("%d\n", i);
    	}
    	return 0;
    }
    

    啥都不输出,因为:

    1、sizeof()返回的是unsigned int类型

    2、有符号数与无符号数进行运算时,有符号数先自动转换成无符号数

    因此"i < sizeof(int)"比较时-1会转换成unsigned int类型,溢出到unsigned int的最大值,导致大于sizeof(int)
     

    int main(void)
    {
    	unsigned int a = 6;
    	int b = -20;
    	int c = a + b;
    	printf("b = %u\n", b); // b = 4294967276
    	printf("a + b = %u\n", a + b); // a + b = 4294967282
    	printf("a + b = %d\n", a + b); // a + b = -14
    
    	if ((a + b) > 0) {
    		printf("a + b > 0\n"); // a + b > 0
    	} else {
    		printf("a + b <= 0\n");
    	}
    	
    	if (c > 0) {
    		printf("c > 0\n");
    	} else {
    		printf("c <= 0\n"); // c <= 0
    	}
    	return 0;
    }
    

    1、a+b,b要转为无符号,即4294967276,可以理解为无符号下-20,

    再加a就是4294967282,即ffff fff2,可以理解为无符号下-14,因此输出回%d有符号十进制就是-14

    2、a+b的值是ffff fff2,肯定大于0,所以输出a + b > 0

    3、c是int类型有符号整数,所以同%d输出一样,无符号下-14值转有符号十进制是-14,所以c小于0
     

    int main(void)
    {
    	signed short i = 65535;
    	printf("%d\n", i);
    	return 0;
    }
    

    i为-1。因为short占2字节,所以是16位,

    short最大值为0111 1111 1111 1111,为32767

    short最小值为1000 0000 0000 0000,首位为符号位,1代表负数所以得转为原码

    首位符号位取反,其余所有位也取反后最后一位加1

    即0111 1111 1111 1111 + 1 = 1000 0000 0000 0000即32768,所以该负数的原码为32768,该负数为-32768

    65535比32767溢出32768,而溢出1就是-32768,因此溢出32768偏移32767就是-32768+32767=-1。
     

    总结,无符号数与有符号数的运算原则如下:

    1、参与运算的类型不同,会自动转换成相同类型再运算。

    2、转换的方向为向数据长度增长的方向,char->short->int->unsigned int ->long

    3、所有float都会先转成double进行运算,哪怕只有一个float

    4、赋值运算时,赋值号右边的类型向左边的类型转换。

    5、浮点数和整形数,整形数向浮点数转换。

    6、在表达式中,如果char和short类型的值进行运算,无论char和short有无符号,结果都会自动转换成int。

    7、如果char或short与int类型进行计算,结果和int类型相同。即:如果int是有符号,结果就是带符号的,如果int是无符号的,结果就是无符号的。

    展开全文
  • 关于无符号数和有符号数的运算,在我看来一直是觉得只要有无符号数和有符号数的运算,有符号数就转化为无符号数,但是在《C++ Primer 第五版》的p142介绍,关于无符号数和有符号数的运算如下规定的: (1)无符号...

    1.关于无符号数和有符号数的运算

               关于无符号数和有符号数的运算,在我看来一直是觉得只要有无符号数和有符号数的运算,有符号数就转化为无符号数,但是在《C++ Primer 第五版》的p142介绍,关于无符号数和有符号数的运算如下规定的:

                  (1)无符号数类型>=有符号类型(一直不理解这里的不小于是什么意思),则带符号的运算对象转换为无符号。

                  (2)无符号数类型<有符号类型,转换结果和机器有关。如果无符号类型的所有值都能在有符号的类型中找到对应(也就是说有符号类型最起码比无符号类型的数据范围宽),则无符号类型转换为有符号类型,否则有符号类型转化为无符号类型。

                为了验证上述理论,在VS2015下编写如下测试代码:

            (1)测试代码案例1:-3 ( int ) + 5( unsigned int )

                                        

               (2) 测试代码案例3: -7 ( long long ) +5 ( unsigned int )

                            

                (3) 测试代码案例2:-7 ( int ) + 5 (unsigned int )

                               
         

               三个测试代码案例分别对应上述所示三种情况:1)无符号类型数5>有符号类型数3,有符号的数变为无符号的数,则-3变成无符号数4294967293,和5做加法后得到4294967298,超出了32位无符号的最大值4294967295,则得到的值为4294967298%4294967296=2;2)无符号类型的数5<有符号类型的数-7,且unsigned int类型的数都能在long long里面找到对应的数,因此无符号类型的数转化为有符号的数,结果为-7+5=-2;3)无符号类型的数5<有符号类型的数-7,但是unsigned int类型里面有一半的数在int类型里面找不到对应的数,因此有符号的数转化为无符号的数,-7转化为4294967289,加上5之后,结果就变为4294967294.

              因此,得出结论,书中p142页所讲的无符号类型的大小比较,其实是两个数的绝对值比较

    展开全文
  • 1、有符号数与无符号数之间运算问题 ...因此,从这个意义上讲,无符号数的运算优先级要高于有符号数,这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。  首先进行一个实验,分别定
  • 在FPGA设计中,所有的算数运算符都是按照无符号数进行的。如果要完成有符号数计算,对于加、减操作通过补码处理即可...因为只要有一个无符号数的运算单元,整个算式将被将成无符号数进行计算。  总之,正数和负数...
  • C语言中有符号数和无符号数进行运算默认会将有符号数看成无符号数进行运算,其中算术运算默认返回无符号数,逻辑运算当然是返回0或1了。下面通过一个例子给大家分享C语言中无符号数和有符号数之间的运算,一起看看吧
  • 有符号数与无符号数的运算

    千次阅读 2015-03-31 16:29:51
    有符号数与无符号数的运算规则如下: 表达式中既有无符号数又有有符号数,则有符号数会自动转换为无符号数,然后进行计算。such as: int i; unsigned j; cout ; 首先将i自动转换成无符号数,然后与j相加,输出...
  • C/C++中有符号数和无符号数的运算
  • 有符号数与无符号数混合运算时,把有符号数转化为无符号数,再合并运算(换句话说就是),得到结果是无符号数。 #include <stdio.h> #include <math.h> int main() { int x=-100; unsigned y=1; ...
  • 1、有符号数及该数的二进制形式的最高位表示正负,0表示正,1表示负; 无符号数的二进制形式所有位均表示数值,相当于始终是一个正值。 2、当一个表达式的两个操作数分别是无符号数和有符号数时,所有操作数自动...
  • 本文介绍了C语言中有符号数和无符号数之间进行运算的规则。
  • 感谢博主分享,转自:C++ 有符号数与无符号数混合运算 当算术表达式中既有无符号数又有带符号数时,那么在进行运算之前,这个带符号数值会先被转换成无符号数!然后再进行运算。如, unsigned i = 10; int j = -...
  • 有符号数与无符号数之间运算问题以下实验均在...因此,从这个意义上讲,无符号数的运算优先级要高于有符号数,这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。首先进行一个实验,分别定义一个s...
  • 先说自己看书与调试结论:在有符号与无符号一起运算的时候,正数就是正数,负数就是负数,计算机正常做加减运算,但是运算的结果会被程序当成无符号数。 验证过程: 1、测试代码 test.cpp #include<...
  • C语言无符号数跟有符号数之间运算 先来看一个程序: 运行结果: 刚刚无意中发现,第一反应觉得有问题,n是无符号型,不可能等于-1,因此不可能跳出循环,但结果却跳出了循环,也就是说无...
  • 有符号数与无符号数之间运算 ...因此,从这个意义上讲,无符号数的运算优先级要高于有符号数,这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。  首先进行一个实验,分别定义一个signed int

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,178
精华内容 2,071
关键字:

有符号数的运算