zoukankan      html  css  js  c++  java
  • 为什么一个 byte 的存储范围是 -128 ~ 127

    我们知道,对于有符号类型,计算机在处理的时候会把最高位当做符号位,0表示正数,1表示负数。举例来说(以下举例均针对8位有符号数):

    0000 0001即为11000 0001即为-1,那么很容易得到8位有符号数值的表示范围应该是1111 1111 0111 1111,也就是-127~127,问题来了,-128是怎么来的呢?

    在说明这个问题之前,先来补充点额外的知识:


    在计算机的存储和计算中,统一的是采用补码进行处理和运算的,在弄清楚采用补码的好处之前,我们需要明确如下三个概念:

    原码:是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。

    反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。

    补码:正数的补码与其原码相同;负数的补码等于其反码+1。

    很明显,文章开头的举例即是原码,它很符合我们的直观感觉,但是在计算的时候麻烦就来了,如果直接运算,例如1+(-1)=0,运算的时候0000 0001 + 1000 0001 = 1000 0010(-2),很显然是错误的,因此符号位和数值位必须分开处理!这会增加计算机的硬件开销。我们换成补码试试,1的原码0000 0001,反码0000 0001,补码0000 0001(正数三者一致);-1的原码1000 0001,反码1111 1110,补码1111 1111(1111 1110 + 0000 0001);因此1+(-1)用补码来运算就是0000 0001 + 1111 11111 = 0000 0000(最高位溢出舍弃),结果是正确的。

    由此可见,可以将减法运算转化成加法运算,计算机只需要实现加法电路即可,并且原码到补码的转换和补码到原码的转换过程是完全一致的,为什么?可以简单证明如下:

    假设32位机器,X为负数(最高位是符号位,对于负数,即为1),则有X(绝对值)+X(反)=0xFFFFFFFFF,因此X(绝对值)+X(反)+1=0xFFFFFFFFF+1=0;所以得到 0-X(绝对值)=X(反)+1,根据之前的定义X(反)+1即为X的补码,于是有X(补)=X(反)+1=0-X(绝对值)

    1)那么对于A、B>0,令K=-B,显然K是负数,那么有A-B=A+(0-K(绝对值))=A+K(补),减法运算就转化成了加法运算。

    2)X(绝对值)=0-X(补);两边同时乘以-1 得到-X(绝对值)=-0-(-X(补))=0-(X(补(绝对值)))=X(补)(反)+1;-X(绝对值)即为原码X;因此上式说明了原码X等于X的补码取反后加一,也就是说X补码的补码就是原码。不论是原码求补码还是补码求原码方式完全一致。


    回到最开始的问题,8位有符号数值的最小值为什么是-128而不是-127呢,我们列出来部分原码、反码和补码的对照表看看:

    从上表中我们可以看出,0在原码和反码中有两种表示方式,而对应的补码只有一种表示方式,-128在原码和反码中无法表示,在补码中却可以表示(用-127的补码1000 0001减1得到1000 0000)。而计算机中数值以补码形式存储和运算,当然-128可以表示出来,因此8位有符号数值的范围是-128~127,同理其他位数(16、32、64)也可以以此类推。

    说白了就是 在 -0 跟+0 的源码  一个是 1000 0000  跟  0000 0000  这俩个是重复的,但是-0不要浪费了 跟补码是一样的 让它表示-128也可以。

    关注公众号 海量干货等你
  • 相关阅读:
    SpringMVC后台token防重复提交解决方案
    浅析微信支付:开通免充值产品功能及如何进行接口升级指引
    浅析微信支付:查询订单和关闭订单
    浅析微信支付:商户平台代金券或立减优惠开通、指定用户代金券发放、查询等
    linux内核源码分析
    linux内存源码分析
    linux内存源码分析
    linux内存源码分析
    linux内存源码分析
    linux内存源码分析
  • 原文地址:https://www.cnblogs.com/sowhat1412/p/12734179.html
Copyright © 2011-2022 走看看