Math.abs(Integer.MIN_VALUE)问题分析

Math.abs(Integer.MIN_VALUE)问题分析

Android小彩虹2021-08-20 0:53:47350A+A-

日常刷题中,然后有个地方是要求将当前数变成绝对值才可以使用;然后开开心心写了如下代码:

long a = Math.abs(Integer.MIN_VALUE);
System.out.println(a);

结果结果却让我大跌眼镜。但是一番分析下来倒是很有意思 运行结果

点开源码(JDK1.8环境下)

源码 这段话翻译过来就是,如果abs方法输入参数为正数,就返回那个值;如果未负数,就返回这个负数的对应绝对值;但是如果输入值为Integer.MIN_VALUE时;就返回输入值

这样看起来问题是解决了,但是身为一个合格的程序员,怎么可以不弄清楚原因呢。

1.原因分析

要讲清上面发生的原因,就必须把几个核心的问题都讲清楚;

1.1 原码

一开始人们是通过原码来表示整数,整数有正负之分,便通过符号位+二进制的方式表示。(最高位(最左边)取0表示正数,取1表示负数。然后加上对应的二进制。

+1 = 0000 0001 -1 = 1000 0001

1.2 反码

正数的反码是其本身 负数的反码是符号位不变 ,其他位都变为反

[+1] = [00000001]原 = [00000001]反 [-1] = [10000001]原 = [11111110]反

1.3 补码

正数的补码就是其本身 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

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

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

那么为何要使用补码呢?

因为计算机中没有减法的概念,对应减法 a-b = a+(-b);

举个栗子

反码的方式

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2 1 - 1 = 1 + (-1) = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0 补码的方式 1 - 1 = 1 + (-1) = [0000 0001]补 +[1111 1111]补 = [0000 0000]补=0

所以这里如果1.8的jdk不限制,就容易导致结果错误;可以理解为

MIN_VALUE[反] = 0x80000000 = 10....0(中间29个0)= 1......1(中间30个1)

MIN_VALUE[补] = 0x80000000 = 10....0(中间29个0) = 1......1(中间30个1)+1 = 0......0(中间30个1)

所以 这里错误了;而且可以发现超出限制后,会形成一个循环

测试

结果

所以可以理解为为了防止这样的循环发生,JDK1.8出现这个保护的模式;而一切的发生源头就是补码导致

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示 | 支付宝红包
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们