国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

[Java解惑]數(shù)值表達式

2019-11-14 22:46:06
字體:
供稿:網(wǎng)友
[java解惑]數(shù)值表達式聲明:原創(chuàng)作品,轉(zhuǎn)載時請注明文章來自SAP師太技術博客( 博/客/園www.cnblogs.com):m.survivalescaperooms.com/jiangzhengjun,并以超鏈接形式標明文章原始出處,否則將追究法律責任!原文鏈接:http://m.survivalescaperooms.com/jiangzhengjun/p/4257565.html

數(shù)值表達式... 2 1. 奇偶判斷... 2 2. 小數(shù)精確計算... 2 3. int整數(shù)相乘溢出... 3 4. 負的十六進制與八進制字面常量... 3 5. 窄數(shù)字類型提升至寬類型時使用符號位擴展還是零擴展... 4 6. ((byte)0x90 == 0x90)?. 5 7. 三元表達式(?:)... 5 8. +=復合賦值問題... 6 9. i =++i;與i=i++;的區(qū)別... 7 10. Integer.MAX_VALUE + 1=?. 8 11. -1<<32=?、-1<<65=?. 8 12. 一個數(shù)永遠不會等于它自己加1嗎?i==i+1. 9 13. 自己不等于自己嗎?i!=i10 14. 自動拆箱... 10 15. 為什么-0x00000000==0x00000000、-0x80000000== 0x80000000. 10 16. Math.abs結(jié)果一定為非負數(shù)嗎?. 12 17. 不要使用基于減法的比較器... 12 18. int i=-2147483648與int i=-(2147483648)?. 13

數(shù)值表達式1. 奇偶判斷

不要使用 i % 2 == 1 來判斷是否是奇數(shù),因為i為負奇數(shù)時不成立,請使用 i % 2 != 0 來判斷是否是奇數(shù),或使用高效式 (i & 1) != 0來判斷。

2. 小數(shù)精確計算

System.out.PRintln(2.00 -1.10);//0.8999999999999999 上面的計算出的結(jié)果不是 0.9,而是一連串的小數(shù)。問題在于1.1這個數(shù)字不能被精確表示為一個double,因此它被表示為最接近它的double值,該程序從2中減去的就是這個值,但這個計算的結(jié)果并不是最接近0.9的double值。 一般地說,問題在于并不是所有的小數(shù)都可以用二進制浮點數(shù)精確表示。 二進制浮點對于貨幣計算是非常不適合的,因為它不可能將1.0表示成10的其他任何負次冪。 解決問題的第一種方式是使用貨幣的最小單位(分)來表示:System.out.println(200-110);//90 第二種方式是使用BigDecimal,但一定要用BigDecimal(String)構(gòu)造器,而千萬不要用BigDecimal(double)來構(gòu)造(也不能將float或double型轉(zhuǎn)換成String再來使用BigDecimal(String)來構(gòu)造,因為在將float或double轉(zhuǎn)換成String時精度已丟失)。例如new BigDecimal(0.1),它將返回一個BigDecimal,也即0.1000000000000000055511151231257827021181583404541015625,正確使用BigDecimal,程序就可以打印出我們所期望的結(jié)果0.9: System.out.println(newBigDecimal("2.0").subtract(newBigDecimal("1.10")));// 0.9 另外,如果要比較兩個浮點數(shù)的大小,要使用BigDecimal的compareTo方法。

3. int整數(shù)相乘溢出

我們計算一天中的微秒數(shù): long microsPerDay = 24 * 60 * 60 * 1000 * 1000;// 正確結(jié)果應為:86400000000 System.out.println(microsPerDay);// 實際上為:500654080 問題在于計算過程中溢出了。這個計算式完全是以int運算來執(zhí)行的,并且只有在運算完成之后,其結(jié)果才被提升為long,而此時已經(jīng)太遲:計算已經(jīng)溢出。 解決方法使計算表達式的第一個因子明確為long型,這樣可以強制表達式中所有的后續(xù)計算都用long運算來完成,這樣結(jié)果就不會溢出: long microsPerDay = 24L * 60 * 60 * 1000 * 1000;

4. 負的十六進制與八進制字面常量

“數(shù)字字面常量”的類型都是int型,而不管他們是幾進制,所以“2147483648”、“0x180000000(十六進制,共33位,所以超過了整數(shù)的取值范圍)”字面常量是錯誤的,編譯時會報超過int的取值范圍了,所以要確定以long來表示“2147483648L”、“0x180000000L”。 十進制字面常量只有一個特性,即所有的十進制字面常量都是正數(shù),如果想寫一個負的十進制,則需要在正的十進制字面常量前加上“-”即可。 十六進制或八進制字面常量可就不一定是正數(shù)或負數(shù),是正還是負,則要根據(jù)當前情況看:如果十六進制和八進制字面常量的最高位被設置成了1,那么它們就是負數(shù): System.out.println(0x80);//128 //0x81看作是int型,最高位(第32位)為0,所以是正數(shù) System.out.println(0x81);//129 System.out.println(0x8001);//32769 System.out.println(0x70000001);//1879048193 //字面量0x80000001為int型,最高位(第32位)為1,所以是負數(shù) System.out.println(0x80000001);//-2147483647 //字面量0x80000001L強制轉(zhuǎn)為long型,最高位(第64位)為0,所以是正數(shù) System.out.println(0x80000001L);//2147483649 //最小int型 System.out.println(0x80000000);//-2147483648 //只要超過32位,就需要在字面常量后加L強轉(zhuǎn)long,否則編譯時出錯 System.out.println(0x8000000000000000L);//-9223372036854775808 從上面可以看出,十六進制的字面常量表示的是int型,如果超過32位,則需要在后面加“L”,否則編譯過不過。如果為32,則為負int正數(shù),超過32位,則為long型,但需明確指定為long。 System.out.println(Long.toHexString(0x100000000L + 0xcafebabe));// cafebabe 結(jié)果為什么不是0x1cafebabe?該程序執(zhí)行的加法是一個混合類型的計算:左操作數(shù)是long型,而右操作數(shù)是int類型。為了執(zhí)行該計算,Java將int類型的數(shù)值用拓寬原生類型轉(zhuǎn)換提升為long類型,然后對兩個long類型數(shù)值相加。因為int是有符號的整數(shù)類型,所以這個轉(zhuǎn)換執(zhí)行的是符號擴展。 這個加法的右操作數(shù)0xcafebabe為32位,將被提升為long類型的數(shù)值0xffffffffcafebabeL,之后這個數(shù)值加上了左操作0x100000000L。當視為int類型時,經(jīng)過符號擴展之后的右操作數(shù)的高32位是1,而左操作數(shù)的第32位是1,兩個數(shù)值相加得到了0: 0x ffffffffcafebabeL +0x 0000000100000000L ----------------------------- 0x 00000000cafebabeL 如果要得到正確的結(jié)果0x1cafebabe,則需在第二個操作數(shù)組后加上“L”明確看作是正的long型即可,此時相加時拓展符號位就為0: System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL));// 1cafebabe

5. 窄數(shù)字類型提升至寬類型時使用符號位擴展還是零擴展

System.out.println((int)(char)(byte)-1);// 65535 結(jié)果為什么是65535而不是-1? 窄的整型轉(zhuǎn)換成較寬的整型時符號擴展規(guī)則:如果最初的數(shù)值類型是有符號的,那么就執(zhí)行符號擴展(即如果符號位為1,則擴展為1,如果為零,則擴展為0);如果它是char,那么不管它將要被提升成什么類型,都執(zhí)行零擴展。 了解上面的規(guī)則后,我們再來看看迷題:因為byte是有符號的類型,所以在將byte數(shù)值-1(二進制為:11111111)提升到char時,會發(fā)生符號位擴展,又符號位為1,所以就補8個1,最后為16個1;然后從char到int的提升時,由于是char型提升到其他類型,所以采用零擴展而不是符號擴展,結(jié)果int數(shù)值就成了65535。 如果將一個char數(shù)值c轉(zhuǎn)型為一個寬度更寬的類型時,只是以零來擴展,但如果清晰表達以零擴展的意圖,則可以考慮使用一個位掩碼: int i = c & 0xffff;//實質(zhì)上等同于:int i = c ; 如果將一個char數(shù)值c轉(zhuǎn)型為一個寬度更寬的整型,并且希望有符號擴展,那么就先將char轉(zhuǎn)型為一個short,它與char上個具有同樣的寬度,但是它是有符號的: int i = (short)c; 如果將一個byte數(shù)值b轉(zhuǎn)型為一個char,并且不希望有符號擴展,那么必須使用一個位掩碼來限制它: char c = (char)(b & 0xff);// char c = (char) b;為有符號擴展

6. ((byte)0x90 == 0x90)?

答案是不等的,盡管外表看起來是成立的,但是它卻等于false。為了比較byte數(shù)值(byte)0x90和int數(shù)值0x90,Java通過拓寬原生類型將byte提升為int,然后比較這兩個int數(shù)值。因為byte是一個有符號類型,所以這個轉(zhuǎn)換執(zhí)行的是符號擴展,將負的byte數(shù)值提升為了在數(shù)字上相等的int值(10010000à111111111111111111111111 10010000)。在本例中,該轉(zhuǎn)換將(byte)0x90提升為int數(shù)值-112,它不等于int數(shù)值的0x90,即+144。 解決辦法:使用一個屏蔽碼來消除符號擴展的影響,從而將byte轉(zhuǎn)型為int。 ((byte)0x90 & 0xff)== 0x90

7. 三元表達式(?:)

char x = 'X'; int i = 0; System.out.println(true ? x : 0);// X System.out.println(false ? i : x);// 88 條件表達式結(jié)果類型的規(guī)則: (1) 如果第二個和第三個操作數(shù)具有相同的類型,那么它就是條件表達式的類型。 (2) 如果一個操作的類型是T,T表示byte、short或char,而另一個操作數(shù)是一個int類型的“字面常量”,并且它的值可以用類型T表示,那條件表達式的類型就是T。 (3) 否則,將對操作數(shù)類型進行提升,而條件表達式的類型就是第二個和第三個操作被提升之后的類型。 現(xiàn)來使用以上規(guī)則解上面的迷題,第一個表達式符合第二條規(guī)則:一個操作數(shù)的類型是char,另一個的類型是字面常量為0的int型,但0可以表示成char,所以最終返回類型以char類型為準;第二個表達式符合第三條規(guī)則:因為i為int型變量,而x又為char型變量,所以會先將x提升至int型,所以最后的結(jié)果類型為int型,但如果將i定義成final時,則返回結(jié)果類型為char,則此時符合第二條規(guī)則,因為final類型的變量在編譯時就使用“字面常量0”來替換三元表達式了: final int i = 0; System.out.println(false ? i : x);// X 在JDK1.4版本或之前,條件操作符 ?: 中,當?shù)诙€和延續(xù)三個操作數(shù)是引用類型時,條件操作符要求它們其中一個必須是另一個的子類型,那怕它們有同一個父類也不行: public class T { public static void main(String[] args) { System.out.println(f()); } public static T f() { // !!1.4不能編譯,但1.5可以 // !!return true?new T1():new T2(); return true ? (T) new T1() : new T2();// T1 } } class T1 extends T { public String toString() { return "T1"; } } class T2 extends T { public String toString() { return "T2"; } } 在5.0或以上版本中,條件操作符在第二個和第三個操作數(shù)是引用類型時總是合法的。其結(jié)果類型是這兩種類型的最小公共超類。公共超類總是存在的,因為Object是每一個對象類型的超類型,上面的最小公共超類是T,所以能編譯。

8. +=復合賦值問題

x+=i與x=x+i等效嗎,許多程序員都會認為第一個表達式x+=i只是第二個表達式x=x+i的簡寫方式,但這并不準確。 Java語言規(guī)范中提到:復合賦值 E1 op= E2等價于簡單賦值 E1 = (T)((E1) op (E2)),其中T是E1的類型。 復合賦值表達式自動地將所執(zhí)行計算的結(jié)果轉(zhuǎn)型為其左側(cè)變量的類型。如果結(jié)果的類型與該變量的類型相同,那么這個轉(zhuǎn)型不會造成任何影響,然而,如果結(jié)果的類型比該變量的類型要寬,那么復合賦值操作符將悄悄地執(zhí)行一個窄化原生類型轉(zhuǎn)換,這樣就會導致結(jié)果不正確: short x=0; int i = 123456; x +=i; System.out.println(x);//-7616 使用簡單的賦值方式就不會有這樣的問題了,因為寬類型不能自動轉(zhuǎn)換成窄的類型,編譯器會報錯,這時我們就會注意到錯誤:x = x + i;//編譯通不過 請不要將復合賦值操作符作用于byte、short或char類型的變量;在將復合賦值操作符作用于int類型的變量時,要確保表達式右側(cè)不是long、float或double類型;在將復合賦值操作符作用于float類型的變量時,要確保表達式右側(cè)不是double類型。其實一句:不要將讓左側(cè)的類型窄于右側(cè)的數(shù)字類型。 總之,不要在short、byte或char類型的變量之上使用復合賦值操作符,因為這一過程會伴隨著計算前類型的提升與計算后結(jié)果的截斷,導致最后的計算結(jié)果不正確。

9. i =++i;與i=i++;的區(qū)別

int i = 0; i = i++; System.out.println(i); 上面的程序會輸出什么?大部分會說是 1,是也,非也。運行時正確結(jié)果為0。 i=++i;相當于以下二個語句(編譯時出現(xiàn)警告,與i=i;警告相同): i=i+1; i=i; i = i++;相當于以下三個語句: int tmp = i; i = i + 1; i = tmp; 下面看看下面程序片段: int i = 0, j = 0, y = 0; i++;//相當于:i=i+1; System.out.println("i=" + i);// i=1 ++i;//相當于:i=i+1; System.out.println("i=" + i);// i=2 i = i++;//相當于:int tmp=i;i=i+1;i=tmp; System.out.println("i=" + i);// i=2 i = ++i;//編譯時出現(xiàn)警告,與i=i;警告相同。相當于:i=i+1;i=i; System.out.println("i=" + i);// i=3 j = i++;//相當于:int tmp=i;i=i+1;j=tmp; System.out.println("j=" + j);// j=3 System.out.println("i=" + i);// i=4 y = ++i;//相當于:i=i+1;y=i; System.out.println("y=" + y);// y=5 System.out.println("i=" + i);// i=5

10.Integer.MAX_VALUE + 1=?

System.out.println(Integer.MAX_VALUE + 1); 上面的程序輸出多少?2147483647+1=2147483648?答案為-2147483648。 查看源碼Integer.MAX_VALUE 為MAX_VALUE = 0x7fffffff;所以加1后為0x80000000,又0x80000000為整型字面常量,滿了32位,且最位為1,所以字面上等于 -0,但又由于 -0就是等于0,所以-0這個編碼就規(guī)定為最小的負數(shù),32位的最小負數(shù)就是-2147483648。

11.-1<<32=?、-1<<65=?

如果左操作數(shù)是int(如果是byte、short、char型時會提升至int型再進行位操作)型,移位操作符只使用其右操作數(shù)的低5位作為移位長度(也就是將右操作數(shù)除以32取余);如果左操作數(shù)是long型,移位操作符只使用其右操作數(shù)的低6位作為移位長度(也就是將右操作數(shù)除以64取余); 再看看下面程序片段就會知道結(jié)果: System.out.println(-1 << 31);// -2147483648 向左移31%32=31位 System.out.println(-1 << 32);// -1 向左移32%32=0位 System.out.println(-1 << 33);// -2 向左移33%32=1位 System.out.println(-1 << 1);// -2 向左移1%32=1位 System.out.println(-1L << 63);// -9223372036854775808 向左移63%64=63位 System.out.println(-1L << 64);// -1 向左移64%64=0位 System.out.println(-1L << 65);// -2 向左移65%64=1位 System.out.println(-1L << 1);// -2 向左移1%64=1位 byte b = -1;// byte型在位操作前類型提升至int System.out.println(b << 31);// -2147483648 向左移31%32=31位 System.out.println(b << 63);// -2147483648 向左移63%32=31位 short s = -1;// short型在位操作前類型提升至int System.out.println(s << 31);// -2147483648 向左移31%32=31位 System.out.println(s << 63);// -2147483648 向左移63%32=31位 char c = 1;// char型在位操作前類型提升至int System.out.println(c << 31);// -2147483648 向左移31%32=31位 System.out.println(c << 63);// -2147483648 向左移63%32=31位

12.一個數(shù)永遠不會等于它自己加1嗎?i==i+1

一個數(shù)永遠不會等于它自己加1,對嗎?如果數(shù)字是整型,則對;如果這個數(shù)字是無窮大或都是浮點型足夠大(如1.0e40),等式就可能成立了。 Java強制要求使用IEEE 754浮點數(shù)算術運算,它可以讓你用一個double或float來表示無窮大。 浮點型分為double型、float型。 無窮分為正無窮與負無窮。 無窮大加1還是無窮大。 一個浮點數(shù)值越大,它和其后繼數(shù)值之間的間隔就越大。 對一個足夠大的浮點數(shù)加1不會改變它的值,因為1不足以“填補它與其后者之間的空隙”。 浮點數(shù)操作返回的是最接近其精確數(shù)學結(jié)果的浮點數(shù)值。 一旦毗鄰的浮點數(shù)值之間的距離大于2,那么對其中的一個浮點數(shù)值加1將不會產(chǎn)生任何效果,因為其結(jié)果沒有達到兩個數(shù)值之間的一半。對于float類型,加1不會產(chǎn)生任何效果的最小數(shù)是2^25,即33554432;而對于double類型,最小數(shù)是2^54,大約是1.8*10^16。 33554432F轉(zhuǎn)二進制過程: 33554432的二進制為:10000000000000000000000000,將該二進制化成規(guī)范的小數(shù)二進制,即小數(shù)從右向左移25位1.0000000000000000000000000,化成浮點數(shù)二進制0,25+127, 00000000000000000000000 00(丟棄最后兩位),即0, 10011000, 00000000000000000000000,最后的結(jié)果為1.00000000000000000000000*2^25 毗鄰的浮點數(shù)值之間的距離被稱為一個ulp,它是最小單位(unit in the last place)的首字母縮寫。在5.0版本中,引入了Math.ulp方法來計算float或double數(shù)值的ulp。 二進制浮點算術只是對實際算術的一種近似。 // 注,整型數(shù)不能被 0 除,即(int)XX/0運行時拋異常 double i = 1.0 / 0.0;// 正無窮大 double j = -1.0 / 0.0;// 負無窮大 // Double.POSITIVE_INFINITY定義為:POSITIVE_INFINITY = 1.0 / 0.0; System.out.println(i + " " + (i == Double.POSITIVE_INFINITY));//Infinity true // Double.NEGATIVE_INFINITY定義為:NEGATIVE_INFINITY = -1.0 / 0.0; System.out.println(j + " " + (j == Double.NEGATIVE_INFINITY));//-Infinity true System.out.println(i == (i + 1));// true System.out.println(0.1f == 0.1);// false float f = 33554432; System.out.println(f + " " + (f==(f+1)));//3.3554432E7 true

13.自己不等于自己嗎?i!=i

NaN(Not a Number)不等于任何數(shù),包括它自身在內(nèi)。 double i = 0.0/0.0;可表示NaN。 float和double類型都有一個特殊的NaN值,Double.NaN、Float.NaN表示NaN。 如果一個表達式中產(chǎn)生了NaN,則結(jié)果為NaN。 System.out.println(0.0 / 0.0);// NaN System.out.println(Double.NaN + " " + (Double.NaN == (0.0 / 0.0)));//NaN false

14.自動拆箱

// 為了兼容以前版本,1.5不會自動拆箱 System.out.println(new Integer(0) == new Integer(0));// false // 1.4編譯非法,1.5會自動拆箱 System.out.println(new Integer(0) == 0);// true

15.為什么-0x00000000==0x00000000、-0x80000000== 0x80000000

十六進制(0X開頭)、八進制(0開頭)、以及二進制(0B開頭,JDK1.7已開始支持)表示了內(nèi)存中直接存儲形式,這與十進制是有區(qū)別的。 規(guī)則:為了取一個整數(shù)類型(十六進制、八進制或二進制)的負值,對每一位(即內(nèi)存所存儲的二進制內(nèi)容)取反,然后再加1;但如果是對一個十進制數(shù)求負操作,實質(zhì)上直接求這個十進制整數(shù)的補碼即可,但也可以按照前面對十六進制數(shù)那樣取負操作,只不過先要將這個十進制數(shù)轉(zhuǎn)換為補碼形式再按前面規(guī)則取反后加1。 運用上面的規(guī)則,-0x00000000的運算過程:對0x00000000先取反得到0xffffffff,再加1,-0x00000000的最后結(jié)果就為 0xffffffff+1,其最后的結(jié)果還是0x00000000,所以-0x00000000 == 0x00000000。前面是對0x00000000求負的過程,如果是對0求負呢?按上面的規(guī)則,對0取負就是求-0的補碼即可,根據(jù)后面的規(guī)則,-0的補碼為0x00000000。不過也可采用上面對一個十六進制取負的規(guī)來求,先求0的十六進制形式0x00000000,再按前面的取負過程來即可得到對0取負的結(jié)果也為0x00000000。 運用前面的規(guī)則,-0x80000000的運算過程:對0x80000000先取反得到0x7fffffff,再加1,-0x80000000的最后結(jié)果就為 0x7fffffff+1,其最后的結(jié)果還是0x80000000,即-0x80000000 == 0x80000000。前面是對0x80000000求負的過程,如果是對2147483648求負呢?按上面的規(guī)則,對2147483648取負就是求-2147483648的補碼,并要所后面的規(guī)則,-2147483648的補碼就是0x80000000。不過也可采用上面對一個十六進制取負的規(guī)來求,先求2147483648的十六進制形式0x80000000,再按前面的取負過程來即可得到對2147483648取負的結(jié)果也為0x80000000。 所有的整數(shù)在內(nèi)存中都是以補碼形式存儲的,只不過正數(shù)或零的補碼為本身而已;如果是負數(shù),則對其絕對值取反后加1即是內(nèi)存中存儲形式。求一個負數(shù)的補碼有個比較簡單的規(guī)則:先求這個數(shù)絕對值的原碼,然后從該二進制最末向前開始找第一個為1的位置,最后將這個1之前的各位取反(包括最高位符號位0),其他位不變,最終所得的二進制就為這個負數(shù)的補碼,也就是最終在內(nèi)存中存儲的形式。不過在找這個第一個為1時可能找不到或在最高位,比如-0,其絕對值為0(0x00000000),也有可能這個1在最高位,比如-2147483648,其絕對值為2147483648(0x80000000),如果遇到絕對值的原碼為0x00000000或0x80000000的情況下補碼直接就是0x00000000或0x80000000。 上面是講了原碼到補碼的轉(zhuǎn)換規(guī)則,那怎么由補碼到原碼就簡單了:如果補碼是正的,則說明原碼是正的,所以這時補碼就是原碼;如果補碼是負的,則原碼一定是負的,此時轉(zhuǎn)換過程正好與從負原碼到補碼的轉(zhuǎn)換過程相反,即先將補碼減1,再取反,但符號位不要變,即永遠為1。 // 因為Integer.MIN_VALUE定義成了0xffffffff,所以根據(jù)上面的規(guī)則得到相等的結(jié)論 System.out.println(Integer.MIN_VALUE == -Integer.MIN_VALUE);// true /* * 0x80000000取反得0x7fffffff,再加1得0x80000000,因為負數(shù)是 * 以補碼形式存儲于內(nèi)存中的,所以推導出結(jié)果原碼為:0x80000000, * 即為-0,又因為-0是等于0的,所以不需要-0這個編碼位,否則就多了 * 一個0x80000000編碼位了,所以最后就規(guī)定0x80000000為最小負數(shù) */ System.out.println(-0x80000000);// -2147483648 /* * 0x7fffffff取反得0x80000000,再加1得0x80000001,因為負數(shù)是 * 以補碼形式存儲于內(nèi)存中的,所以推導出0x80000001的原碼為:0xffffffff(取反時 *,第一位為符號位不要變,還是1),所以最后的結(jié)果就為 -0x7fffffff = -2147483647 */ System.out.println(-0x7fffffff);// -2147483647 另外,還發(fā)現(xiàn)有趣現(xiàn)象:最大整數(shù)加1后會等于最小整數(shù): // MAX_VALUE = 0x7fffffff; MIN_VALUE = 0x80000000; System.out.println((Integer.MAX_VALUE + 1) == Integer.MIN_VALUE);// true // MIN_VALUE = 0x8000000000000000L; MIN_VALUE = 0x8000000000000000L; System.out.println((Long.MAX_VALUE + 1) == Long.MIN_VALUE);// true 當然,-Byte. MIN_VALUE==Byte.MIN_VALUE、-Short.MIN_VALUE== Short.MIN_VALUE、-Long.MIN_VALUE== Long.MIN_VALUE,也是成立的。

16.Math.abs結(jié)果一定為非負數(shù)嗎?

System.out.println(Math.abs(Integer.MIN_VALUE));// -2147483648 上面的程序不會輸出2147483648,而是-2147483648,為什么? 其實我們看一下Math.abs源碼就知道為什么了,源碼:(a < 0) ? -a : a;,結(jié)合上面那個迷題,我們就發(fā)現(xiàn)-Integer.MIN_VALUE= Integer.MIN_VALUE,所以上面的答案就是最小整數(shù)自己。 另外我們也可以從API文檔看到對Math.abs()方法的解釋:如果參數(shù)等于 Integer.MIN_VALUE的值(即能夠表示的最小負 int值),則結(jié)果與該值相同且為負。 所以Math.abs不能保證一定會返回非負結(jié)果。 當然,Long.MIN_VALUE也是這樣的。

17.不要使用基于減法的比較器

Comparator<Integer> c = new Comparator<Integer>() { public int compare(Integer i1, Integer i2) { return i1 - i2;// 升序 } }; List<Integer> l = new ArrayList<Integer>(); l.add(new Integer(-2000000000)); l.add(new Integer(2000000000)); Collections.sort(l, c); System.out.println(l);// [2000000000, -2000000000] 上面程序的比較器是升序,結(jié)果卻不是這樣,比較時出現(xiàn)了什么問題? 先看看下面程序片斷: int x = -2000000000; int y = 2000000000; /* * -2000000000 即 -(01110111001101011001010000000000) * 的補碼為: 10001000110010100110110000000000 * * 計算過程使用豎式表示: * 10001000110010100110110000000000 * 10001000110010100110110000000000 * -------------------------------- * 00010001100101001101100000000000 * * 計算結(jié)果溢出,結(jié)果為294967296 */ System.out.println(x - y);// 294967296 所以不要使用減法的比較器,除非能確保要比較的數(shù)值之間的距離永遠不會大于Intger.MAX_VALUE。 基于整型的比較器的實現(xiàn)一般使用如下的方式來比較: public int compare(Integer i1, Integer i2) { return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1)); }

18.int i=-2147483648與int i=-(2147483648)?

int i=-(2147483648); 編譯通不過!為什么 int字面常量2147483638只能作為一元負操作符的操作數(shù)來使用。 類似的還有最大long: long i=–(9223372036854775808L);


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 广水市| 乌拉特前旗| 法库县| 久治县| 迭部县| 项城市| 南充市| 沾益县| 上林县| 肃宁县| 中江县| 云浮市| 保亭| 白河县| 来凤县| 鹤庆县| 靖远县| 济宁市| 鹤壁市| 那曲县| 桃源县| 卓尼县| 乐山市| 电白县| 卓尼县| 赤水市| 齐齐哈尔市| 方正县| 玉山县| 平凉市| 姚安县| 墨脱县| 体育| 长泰县| 剑河县| 汕头市| 托克逊县| 黔江区| 新和县| 新田县| 无锡市|