Java中負(fù)數(shù)的絕對(duì)值竟然不一定是正數(shù)
絕對(duì)值是指一個(gè)數(shù)在數(shù)軸上所對(duì)應(yīng)點(diǎn)到原點(diǎn)的距離,所以,在數(shù)學(xué)領(lǐng)域,正數(shù)的絕對(duì)值是這個(gè)數(shù)本身,負(fù)數(shù)的絕對(duì)值應(yīng)該是他的相反數(shù)。
這幾乎是每個(gè)人都知道的。
在Java中,想要獲得有個(gè)數(shù)字的絕對(duì)值,可以使用java.lang.Math
中的abs
方法,這個(gè)類共有4個(gè)重載的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個(gè)方法分別返回int、long、float、double類型的絕對(duì)值,方法里面的邏輯也簡(jiǎn)單,無非就是整數(shù)直接返回,負(fù)數(shù)取相反數(shù)返回。
所以,基于以上所有的知識(shí),我們經(jīng)常會(huì)直接使用Math.abs
來對(duì)一個(gè)數(shù)字取絕對(duì)值。
在我們的代碼中,也有很多這樣的例子。
比如,我們需要用訂單號(hào)做分庫分表,但是訂單號(hào)是字符串類型,所以,我們就需要取得這個(gè)字符換的hashCode,因?yàn)?strong>hashCode可能是負(fù)數(shù),所以然后再對(duì)hashCode取絕對(duì)值,再用這個(gè)值去對(duì)分表數(shù)取模:
Math.abs(orderId.hashCode()) % 1024;
但是,上面這個(gè)邏輯是有問題的?。。?/p>
因?yàn)樵跇O特殊情況下,上面的代碼會(huì)得到一個(gè)負(fù)數(shù)的值。
**這個(gè)極特殊情況下就是當(dāng)hashCode是Integer.MIN_VALUE,即整數(shù)能表達(dá)的最小值的時(shí)候,**可以代碼驗(yàn)證下:
public static void main(String[] args) { System.out.println(Math.abs(Integer.MIN_VALUE)); }
執(zhí)行以上代碼,得到的結(jié)果是:
-2147483648
很明顯,這是個(gè)負(fù)數(shù)!??!
為什么會(huì)這樣呢?
這要從Integer的取值范圍說起,int的取值范圍是-2^31 —— (2^31) - 1,即-2147483648 至 2147483647
那么,當(dāng)我們使用abs取絕對(duì)值時(shí)候,想要取得-2147483648的絕對(duì)值,那應(yīng)該是2147483648。
但是,2147483648大于了2147483647,即超過了int的取值范圍。這時(shí)候就會(huì)發(fā)生越界。
2147483647用二進(jìn)制的補(bǔ)碼表示是:
01111111 11111111 11111111 11111111
這個(gè)數(shù) +1 得到:
10000000 00000000 00000000 00000000
這個(gè)二進(jìn)制就是-2147483648的補(bǔ)碼。
雖然,這種情況發(fā)生的概率很低,只有當(dāng)要取絕對(duì)值的數(shù)字是-2147483648的時(shí)候,得到的數(shù)字還是個(gè)負(fù)數(shù)。
那么,如何解決這個(gè)問題呢?
既然是以為越界了導(dǎo)致最終結(jié)果變成負(fù)數(shù),那就解決越界的問題就行了,那就是在取絕對(duì)值之前,把這個(gè)int類型轉(zhuǎn)成long類型,這樣就不會(huì)出現(xiàn)越界了。
如,前面我們的分表邏輯修改為
Math.abs((long)orderId.hashCode()) % 1024;
就萬無一失了。
大家可以執(zhí)行下以下代碼:
public static void main(String[] args) { System.out.println(Math.abs((long)Integer.MIN_VALUE)); }
得到的結(jié)果就是:
2147483648
以上,就是今天要介紹的知識(shí)點(diǎn)了。
但是,一定要記得,對(duì)long類型取絕對(duì)值其實(shí)也可能存在這個(gè)情況哦!只不過發(fā)生的概率就更低了,但是只要他存在,就有可能發(fā)生哦!
ps:下面看下Java 中怎么把負(fù)數(shù)轉(zhuǎn)換為正數(shù)?
要將負(fù)數(shù)轉(zhuǎn)換為正數(shù)(這稱為絕對(duì)值),請(qǐng)使用Math.abs()。此Math.abs()
方法的工作方式如下:“number = (number < 0 ? -number : number);
”。
看一個(gè)完整的例子:
package com.mkyong; public class app{ public static void main(String[] args) { int total =1 +1 +1 +1 + (-1); //output 3 System.out.println("Total : " + total); int total2 =1 +1 +1 +1 + Math.abs(-1); //output 5 System.out.println("Total 2 (absolute value) : " + total2); } }
輸出量
Total :3
Total2 (absolute value) :5
在這種情況下,Math.abs(-1)
會(huì)將負(fù)數(shù)1轉(zhuǎn)換為正數(shù)1?! ?/p>
到此這篇關(guān)于Java中負(fù)數(shù)的絕對(duì)值竟然不一定是正數(shù)的文章就介紹到這了,更多相關(guān)java負(fù)數(shù)絕對(duì)值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA+Maven搭建JavaWeb項(xiàng)目的方法步驟
本文主要介紹了IDEA+Maven搭建JavaWeb項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11關(guān)于Process的waitFor死鎖問題及解決方案
這篇文章主要介紹了關(guān)于Process的waitFor死鎖問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Spring Boot如何使用Spring Security進(jìn)行安全控制
要實(shí)現(xiàn)訪問控制的方法多種多樣,可以通過Aop、攔截器實(shí)現(xiàn),也可以通過框架實(shí)現(xiàn),本文將具體介紹在Spring Boot中如何使用Spring Security進(jìn)行安全控制。2017-04-04PowerJob的OmsLogHandler工作流程源碼解析
這篇文章主要為大家介紹了PowerJob的OmsLogHandler工作流程源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12java發(fā)送短信系列之限制日發(fā)送次數(shù)
這篇文章主要為大家詳細(xì)介紹了java發(fā)送短信系列之限制日發(fā)送次數(shù),詳細(xì)介紹了限制每日向同一個(gè)用戶(根據(jù)手機(jī)號(hào)和ip判斷)發(fā)送短信次數(shù)的方法,感興趣的小伙伴們可以參考一下2016-02-02