- 論壇徽章:
- 0
|
java解惑學習筆記:1.【奇數(shù)性】書中談到取余操作的符號時用到了:(a / b) * b + (a % b) == a,來說明a % b的符號和a是相同的。例如:a = -5,b=2,a/b = -2, (a / b) * b = -4,所以a % b必然是-1。修正放案: ★ 1.public static boolean isOdd(int i) { return i % 2 != 0; } ★★2. 對i求絕對值后進行取模運算。 ★★3.public static boolean isOdd(int i) { return (i & 1) != 0; } 2.【找零時刻】 public class Change{ public static void main(String args[]){ System.out.println(2.00 - 1.10); } }真沒想到會打印出那樣的一個結果:0.8999999999999999.暈!真長啊!Double.toString()中描述的規(guī)則是:There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type float. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument f. Then f must be the float value nearest to x; or, if two float values are equally close to x, then f must be one of them and the least significant bit of the significand of f must be 0.(大意是:至少要用一個數(shù)來表達小數(shù)部分,而且盡可能多,但是只需能把這個值和它鄰接的float型數(shù)據(jù)區(qū)分開就足夠了。也就是說,假如x是對于有限非零實參f用這種方式產(chǎn)生的十進制的精確數(shù)學表述,f必定是最接近x的float型數(shù)據(jù),或者如果兩個float值是與x同樣的接近(數(shù)軸上),f必定是它們中的一個并且f的最少有效位必須是0)瞎扯了一大堆還是沒搞明白是什么意思,試試這個double d =2.0;double f = 1.10;double result = d - f;System.out.println(result);打印是仍舊是:0.8999999999999999。原來如此,并不是toString搞得怪,是原本就算錯了。并不是所有的小數(shù)都可以用二進制浮點數(shù)來精確表示的(書上),但是什么樣的浮點數(shù)數(shù)據(jù)是java能過正確表示的????SOLUTION:●1.拙劣的解決方案 - 障眼法System.out.printf("%.2f%n",2.00 - 1.10);★★★2.使用某種整數(shù)類型,例如int和long(較優(yōu))System.out.println((200 - 110) + "cents");★★3.使用執(zhí)行精確小數(shù)運算的BigDecimalimport java.math.BigDecimal;public class Change1{ public static void main(String args[]){ System.out.println(new BigDecimal("2.00"). subtract(new BigDecimal("1.10"))); }}3.【長整除】public class LongDivision{ public static void main(String args[]){ final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000; final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000; System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); }}結果是什么? 還用想肯定是1000。OH my god !活見鬼居然是5.java不具有目標確定類型的特性所以24 * 60 * 60 * 1000 * 1000計算的結果先放在一個中間變量中,最后通過windening conversion提升為long型 ,24 * 60 * 60 * 1000 * 1000 =86400000000 而int型數(shù)據(jù)表示范圍是-2147483648~2147483647很明顯是溢出了。關鍵問題是:在編譯中使用的中間變量是由計算的數(shù)據(jù)決定而不是結果的類型(個人看法)。SOLUTION:public class LongDivision{ public static void main(String args[ ]){ final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000; final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000; System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); }正如書上描述的溢出是一個沉默的殺手,我們在盡力避免它的發(fā)生,沒想到還會遇到這樣的事。即使用來保存結果的變量已顯得足夠大,也并不意味著要產(chǎn)生結果的計算具有正確的類型。當你拿不準時,就使用long運算來執(zhí)行整個計算。(java的這個缺陷也太菜了吧。
本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/28187/showart_241625.html |
|