zoukankan      html  css  js  c++  java
  • 整型计算

    整型计算

    今天做LeetCode看到一道题,翻转整型,其中一行代码if ((newResult - tail) / 10 != result)表示超出范围就会有损失,有点不太明白,正好之前复习过原码,反码,补码这些,研究了半天,写个总结。接下来从两个问题入门看计算机内部是如何计算的。

    1. 为什么Integer.MAX_VALUE + 1 = Integer.MIN_VALUE

    我们可以用java代码测试一下:

    System.out.println(Integer.MAX_VALUE + 1);
    System.out.println(Integer.MIN_VALUE);
    
    打印:
    -2147483648
    -2147483648
    也就是-2^31
    

    我们知道带符号整型的取值范围是[-2^31 ~ 2^31-1],在计算机中是以补码的形式存储的,先来复习一下什么是补码,反码和原码:

    正整数的原码,反码和补码一样,符号位固定为0。
    负整数的符号位为1:
    反码 = 原码各位取反(除第一位符号位)
    补码 = 反码 + 1
    
    以-1为例:
    原码:10000000,00000000,00000000,00000001
    反码:11111111,11111111,11111111,11111110
    补码:11111111,11111111,11111111,11111111
    计算机内部是使用补码存储并且计算的,那么-1-1的过程就是
    -1的补码 11111111,11111111,11111111,11111111 - 1
    得到-2的补码:11111111,11111111,11111111,11111110
    那么-2的反码:11111111,11111111,11111111,11111101
    那么-2的原码:10000000,00000000,00000000,00000010
    

    有了这个基础我们来看一下为什么Integer.MAX_VALUE + 1 = Integer.MIN_VALUE:

    Integer.MAX_VALUE的二进制是:
    01111111,11111111,11111111,11111111
    +1得到
    10000000,00000000,00000000,00000000
    这是补码,根据补码可以得到反码:
    11111111,11111111,11111111,11111111
    注意:可能发现10000000,00000000,00000000,00000000 - 1应该是
    01111111,11111111,11111111,11111111啊,因为负整数符号位不变,因此符号位由0变为1.
    进而得到原码:
    10000000,00000000,00000000,00000000
    因为00000000,00000000,00000000,00000000已经表示为0了,计算机规定10000000,00000000,00000000,00000000就代表负整数的最小值即Integer.MIN_VALUE。
    
    因此Integer.MIN_VALUE的
    补码:10000000,00000000,00000000,00000000
    反码:11111111,11111111,11111111,11111111
    原码:10000000,00000000,00000000,00000000
    
    接着看一下Integer.MIN_VALUE + 1
    补码:10000000,00000000,00000000,00000001
    反码:10000000,00000000,00000000,00000000
    原码:11111111,11111111,11111111,11111111
    

    2. 为什么Integer.MAX_VALUE * 10 = -10

    Integer.MAX_VALUE * 10在计算机内部就是10个Integer.MAX_VALUE相加(好像是...)
    Integer.MAX_VALUE的二进制为:
    01111111,11111111,11111111,11111111
    首先看一下Integer.MAX_VALUE * 2就是
    01111111,11111111,11111111,11111111 +
    01111111,11111111,11111111,11111111 =
    11111111,11111111,11111111,11111110(补码)
    11111111,11111111,11111111,11111101(反码)
    10000000,00000000,00000000,00000010(原码)
    所以Integer.MAX_VALUE * 2 = -2
    可以使用System.out.println(Integer.MAX_VALUE * 2); 验证一下!
    
    接下来可以一步一步计算出Integer.MAX_VALUE * 10,就是10个Integer.MAX_VALUE相加
    最后结果为:
    11111111,11111111,11111111,11110110(补码)
    11111111,11111111,11111111,11110101(反码)
    10000000,00000000,00000000,00001010(原码)
    即-10.
    

    补充:

    为什么计算机内部要用补码进行计算,可以看看这篇文章:

    https://www.cnblogs.com/raytheweak/p/7290617.html

  • 相关阅读:
    linux脚本mysql服务与keepalived服务高可用脚本
    linux脚本启动服务脚本
    linux脚本数据库备份脚本
    linux脚本清理日志文件脚本
    最大数字
    求阶乘
    素数
    水仙花数
    js基础1
    css常用属性2
  • 原文地址:https://www.cnblogs.com/scuwangjun/p/9124610.html
Copyright © 2011-2022 走看看