在Java中,负数的绝对值竟然不一定是正数!!!
绝对值是指一个数在数轴上所对应点到原点的距离,所以,在数学领域,正数的绝对值是这个数本身,负数的绝对值应该是他的相反数。
这几乎是每个人都知道的。
在Java中,想要获得有个数字的绝对值,可以使用java.lang.Math中的abs方法,这个类共有4个重载的abs方法,分别是:
public static int abs(int a) {
return (a < 0) ? -a : a;
}
public static long abs(long a) {
return (a < 0) ? -a : a;
}
public static float abs(float a) {
return (a <= 0.0F) ? 0.0F - a : a;
}
public static double abs(double a) {
return (a <= 0.0D) ? 0.0D - a : a;
}
以上4个方法分别返回int、long、float、double类型的绝对值,方法里面的逻辑也简单,无非就是整数直接返回,负数取相反数返回。
所以,基于以上所有的知识,我们经常会直接使用Math.abs来对一个数字取绝对值。
在我们的代码中,也有很多这样的例子。
比如,我们需要用订单号做分库分表,但是订单号是字符串类型,所以,我们就需要取得这个字符换的hashCode,因为hashCode可能是负数,所以然后再对hashCode取绝对值,再用这个值去对分表数取模:
Math.abs(orderId.hashCode()) % 1024;
但是,上面这个逻辑是有问题的!!!
因为在极特殊情况下,上面的代码会得到一个负数的值。
这个极特殊情况下就是当hashCode是Integer.MIN_VALUE,即整数能表达的最小值的时候,可以代码验证下:
public static void main(String[] args) {
System.out.println(Math.abs(Integer.MIN_VALUE));
}
执行以上代码,得到的结果是:
-2147483648
很明显,这是个负数!!!
为什么会这样呢?
这要从Integer的取值范围说起,int的取值范围是-2^31 —— (2^31) - 1,即-2147483648 至 2147483647
那么,当我们使用abs取绝对值时候,想要取得-2147483648的绝对值,那应该是2147483648。
但是,2147483648大于了2147483647,即超过了int的取值范围。这时候就会发生越界。
2147483647用二进制的补码表示是:
01111111 11111111 11111111 11111111
这个数 +1 得到:
10000000 00000000 00000000 00000000
这个二进制就是-2147483648的补码。
虽然,这种情况发生的概率很低,只有当要取绝对值的数字是-2147483648的时候,得到的数字还是个负数。
那么,如何解决这个问题呢?
既然是以为越界了导致最终结果变成负数,那就解决越界的问题就行了,那就是在取绝对值之前,把这个int类型转成long类型,这样就不会出现越界了。
如,前面我们的分表逻辑修改为
Math.abs((long)orderId.hashCode()) % 1024;
就万无一失了。
大家可以执行下以下代码:
public static void main(String[] args) {
System.out.println(Math.abs((long)Integer.MIN_VALUE));
}
得到的结果就是:
2147483648
以上,就是今天要介绍的知识点了。
但是,一定要记得,对long类型取绝对值其实也可能存在这个情况哦!只不过发生的概率就更低了,但是只要他存在,就有可能发生哦!
关注公众号【Hollis】,后台回复"成神导图"可以咯领取Java工程师进阶思维导图。
在Java中,负数的绝对值竟然不一定是正数!!!的更多相关文章
- java中负数的补码转换为十进制
一个数如果为正,则它的原码.反码.补码相同:一个正数的补码,将其转化为十进制,可以直接转换. 已知一个负数的补码,将其转换为十进制数,步骤: 1.先对各位取反: 2.将其转换为十进制数: 3.加上负号 ...
- Java中正数与负数操作>>、>>>的区别
以下为个人理解,有不对的地方请提出 Java中,>>.>>>都是在数字的二进制的补码中进行的 正数的补码为本身 如33的二进制表示为 00000000 00000000 ...
- (转) Java中的负数及基本类型的转型详解
(转) https://my.oschina.net/joymufeng/blog/139952 面这行代码的输出是什么? 下面两行代码的输出相同吗? 请尝试在Eclipse中运行上面的两个代码片段, ...
- Java中正负数的存储方式-正码 反码和补码
Java中正负数的存储方式-正码 反码和补码 正码 我们以int 为例,一个int占用4个byte,32bits 0 存在内存上为 00000000 00000000 00000000 0000000 ...
- JAVA中计算两个日期时间的差值竟然也有这么多门道
上半年春招的时候,作为面试官,对于面试表现的不错的同学会要求其写一小段代码看看.题目很简单: 给定一个日期,然后计算下距离今天相差的天数. 本以为这么个问题就是用来活跃面试氛围的,但是结果却让人大跌眼 ...
- 我说精通字符串,面试官竟然问我 Java 中的 String 有没有长度限制?
String 是 Java 中很重要的一个数据类型,除了基本数据类型以外,String 是被使用的最广泛的了,但是,关于 String,其实还是有很多东西容易被忽略的. 就如本文我们要讨论的问题:Ja ...
- Java中的数是用补码表示的检验
一.基本介绍(关于下列五个定义来自http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html#!comments,谢原 ...
- JAVA中分为基本数据类型及引用数据类型
一.基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768 ...
- java中的二进制
(1)按位与运算 & 1 & 1 = 1, 0 & 1 = 0 51 & 5 即 0011 0011 & 0000 0101 =0000 0001 = 1 ...
随机推荐
- python+selenium基础篇,网页截图
代码如下: from selenium import webdriver dr=webdriver.Firefox() dr.get("https://www.baidu.com" ...
- 编译原理-DFA与正规式的转化
- 【python学习小知识】求绝对值和numpy和tensor的相互转换
一.python求绝对值的三种方法 1.条件判断 2.内置函数abs() 3.内置模块 math.fabs 1.条件判段,判断大于0还是小于0,小于0则输出相反数即可 # 法1:使用条件判断求绝对值 ...
- 「题解」小 R 打怪兽 monster
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目描述 小 R 最近在玩一款游戏.在游戏中,小 R 要依次打 \(n\) 个怪兽,他需要打败至少 \(k\) 个怪兽才能通关.小 ...
- halcon——缺陷检测常用方法总结(特征训练)
引言 机器视觉中缺陷检测分为一下几种: blob分析+特征 模板匹配(定位)+差分:halcon--缺陷检测常用方法总结(模板匹配(定位)+差分) - 唯有自己强大 - 博客园 (cnblogs.co ...
- Docker开启安全的TLS远程连接
目录 1.1 不安全的远程访问方式 1.1.1 编辑docker.service文件: 1.1.2 重新加载Docker配置生效 1.1.3 警告! 2.1 建立基于TLS数字签名的安全连接 1.1 ...
- ConcurrentSkipListSet - 秒懂
疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 面试必备 + 面试必备 [博客园总入口 ] 疯狂创客圈 经典图书 : <Sprin ...
- 简易版JDBC连接池
JDBC连接池mini版的实现 首先是工具类 DbUtil 主要参数就是Driver.User.PWD等啦,主要用于建立连接 URL需要注意的是SSL和serverTimezone参数,和mysql驱 ...
- 29、Tomcat只允许指定域名访问,禁用IP地址访问,防止恶意解析
1.1.测试环境说明: Linux版本:7.6 IP地址:10.11.220.123/24 Tomcat版本:tomcat-8.5.37(端口号为8080) Jdk版本:1.8.0_202 1.2.配 ...
- 查找----python
class Solution: #顺序查找 def seq_search(self,list,num): for i in(range(len(list))): if list[i] == num: ...