溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

為什么Java中負(fù)數(shù)的絕對(duì)值不一定是正數(shù)

發(fā)布時(shí)間:2021-07-29 13:39:06 來(lái)源:億速云 閱讀:137 作者:chen 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“為什么Java中負(fù)數(shù)的絕對(duì)值不一定是正數(shù)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“為什么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è)類(lèi)共有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類(lèi)型的絕對(duì)值,方法里面的邏輯也簡(jiǎn)單,無(wú)非就是整數(shù)直接返回,負(fù)數(shù)取相反數(shù)返回。

所以,基于以上所有的知識(shí),我們經(jīng)常會(huì)直接使用Math.abs來(lái)對(duì)一個(gè)數(shù)字取絕對(duì)值。

在我們的代碼中,也有很多這樣的例子。

比如,我們需要用訂單號(hào)做分庫(kù)分表,但是訂單號(hào)是字符串類(lèi)型,所以,我們就需要取得這個(gè)字符換的hashCode,因?yàn)?strong>hashCode可能是負(fù)數(shù),所以然后再對(duì)hashCode取絕對(duì)值,再用這個(gè)值去對(duì)分表數(shù)取模:

Math.abs(orderId.hashCode()) % 1024;

但是,上面這個(gè)邏輯是有問(wèn)題的?。?!

因?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ù)?。。?/p>

為什么會(huì)這樣呢?

這要從Integer的取值范圍說(shuō)起,int的取值范圍是-2^31 —— (2^31) - 1,即-2147483648 至 2147483647

那么,當(dāng)我們使用abs取絕對(duì)值時(shí)候,想要取得-2147483648的絕對(duì)值,那應(yīng)該是2147483648。

但是,2147483648大于了2147483647,即超過(guò)了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è)問(wèn)題呢?

既然是以為越界了導(dǎo)致最終結(jié)果變成負(fù)數(shù),那就解決越界的問(wèn)題就行了,那就是在取絕對(duì)值之前,把這個(gè)int類(lèi)型轉(zhuǎn)成long類(lèi)型,這樣就不會(huì)出現(xiàn)越界了。

如,前面我們的分表邏輯修改為

Math.abs((long)orderId.hashCode()) % 1024;

就萬(wàn)無(wú)一失了。

大家可以執(zhí)行下以下代碼:

public static void main(String[] args) {
    System.out.println(Math.abs((long)Integer.MIN_VALUE));
}

得到的結(jié)果就是:

2147483648

以上,就是今天要介紹的知識(shí)點(diǎn)了。

但是,一定要記得,對(duì)long類(lèi)型取絕對(duì)值其實(shí)也可能存在這個(gè)情況哦!只不過(guò)發(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>

感謝各位的閱讀,以上就是“為什么Java中負(fù)數(shù)的絕對(duì)值不一定是正數(shù)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)為什么Java中負(fù)數(shù)的絕對(duì)值不一定是正數(shù)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI