# 整型计算

今天做LeetCode看到一道题，[翻转整型](https://leetcode.com/problems/reverse-integer/discuss/4060/My-accepted-15-lines-of-code-for-Java)，其中一行代码`if ((newResult - tail) / 10 != result)`表示超出范围就会有损失，有点不太明白，正好之前复习过原码，反码，补码这些，研究了半天，写个总结。接下来从两个问题入门看计算机内部是如何计算的。

## 1. 为什么Integer.MAX\_VALUE + 1 = Integer.MIN\_VALUE

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

```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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/ji-suan-ji-yuan-li/zheng-xing-ji-suan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
