前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中使用Math.abs你入坑了?

Java中使用Math.abs你入坑了?

作者头像
加多
发布2020-06-08 11:28:12
1.2K0
发布2020-06-08 11:28:12
举报
文章被收录于专栏:Java编程技术Java编程技术

一、前言

Math.abs函数是jdk中提供的一个用来返回入参绝对值的函数,也就是你输入一个负数,它会返回其对应绝对值正数,这个在大部分情况下是这样,但是特殊情况下,还是会返回负数,为何那?且往下看。

二、场景介绍

在数据库中当数据量比较大时,我们会把一个表分为多个分表,或者把一个库分为多个库,那么分表按照什么来分那?这里就有一个分表键的概念,比如用户信息表,可以按照用户id作为分表键,比如消息重试表,可以使用消息id来做。

当分表键是字符串时候,我们可以使用字符串的hash值作为分表键。比如我们有100个分表,那么我们可使用hash(分表键)%100取模,根据取模后的值确定当前记录放到哪个分表。

但是字符串的hash值有可能是负数,所以我们需要使用Math.abs取分表键hash值的绝对值%100。这样看起来很好,但是还是会有问题。

因为字符串的hash值是int类型的,所以会取Math.abs(int a)作为取绝对值函数,当a为0x80000000时候,我们会看到其结果为:-2147483648,竟然为负数,然后如果对100取模,则会得到-48,根据-48则我们无法找到对应的分表,因为分表后缀为0-99,所以会出错。

为何会出现上面问题那?其实Math.abs(int a)函数注释已经说明了: Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.

也就是如果参数是整数最小负数,则Math.abs(int a)方法会返回最小负数本身,那么该方法为啥这样做那。其实是因为最大正数为2147483647,而最小负数为-2147483648,对最小负数加绝对值后,已经超过了最大正正数所表达的范围。

那么如何解决那?第一我们可以使用Math.abs(long a)函数,也就是把hash值从整形转换为long型。第二我们可以对hash值做映射,如果hash值为正数最小负数则把其映射为一个固定的正数值即可。

三、总结

细节决定成败,多看,多思考,养成看源码,看使用的工具的注释的习惯,可以极大程度减少线上故障的可能。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、场景介绍
  • 三、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档