Java的困惑-1__java

來源:互聯網
上載者:User

是不是覺得國產翻譯很多經典書籍都搞雜了,我見這本Java Puzzle不錯。網上有英文下載,台灣有個蔡先生好像翻譯了繁體《java解惑》 。我決定用一種簡單的中文文法來翻譯,讓初學java的人都能看懂我在說什麼。如果你看到我在翻譯中有誤認子弟的嚴重錯誤,請務必通知我。因為我也不是很懂哈。email:goddie2046@gmail.com

這本書有很多章節,慢慢來。

英文原文:

-------------------------------------------- Puzzle 1: Oddity

The following method purports to determine whether its sole argument is an odd number. Does the method work?

public static boolean isOdd(int i) {    return i % 2 == 1;}


  Solution 1: Oddity

An odd number can be defined as an integer that is divisible by 2 with a remainder of 1. The expression i % 2 computes the remainder when i is divided by 2, so it would seem that this program ought to work. Unfortunately, it doesn't; it returns the wrong answer one quarter of the time.

Why one quarter? Because half of all int values are negative, and the isOdd method fails for all negative odd values. It returns false when invoked on any negative value, whether even or odd.

This is a consequence of the definition of Java's remainder operator (%). It is defined to satisfy the following identity for all int values a and all nonzero int values b:

(a / b) * b + (a % b) == a


 

In other words, if you divide a by b, multiply the result by b, and add the remainder, you are back where you started [JLS 15.17.3]. This identity makes perfect sense, but in combination with Java's truncating integer division operator [JLS 15.17.2], it implies that when the remainder operation returns a nonzero result, it has the same sign as its left operand.

The isOdd method and the definition of the term odd on which it was based both assume that all remainders are positive. Although this assumption makes sense for some kinds of division [Boxing], Java's remainder operation is perfectly matched to its integer division operation, which discards the fractional part of its result.

When i is a negative odd number, i % 2 is equal to -1 rather than 1, so the isOdd method incorrectly returns false. To prevent this sort of surprise, test that your methods behave properly when passed negative, zero, and positive values for each numerical parameter.

The problem is easy to fix. Simply compare i % 2 to 0 rather than to 1, and reverse the sense of the comparison:

public static boolean isOdd(int i) {    return i % 2 != 0;}


 

If you are using the isOdd method in a performance-critical setting, you would be better off using the bitwise AND operator (&) in place of the remainder operator:

public static boolean isOdd(int i) {    return (i & 1) != 0;}


 

The second version may run much faster than the first, depending on what platform and virtual machine you are using, and is unlikely to run slower. As a general rule, the divide and remainder operations are slow compared to other arithmetic and logical operations. It's a bad idea to optimize prematurely, but in this case, the faster version is as clear as the original, so there is no reason to prefer the original.

In summary, think about the signs of the operands and of the result whenever you use the remainder operator. The behavior of this operator is obvious when its operands are nonnegative, but it isn't so obvious when one or both operands are negative.

 

-------------------------

 

goddie翻譯

-----------------------------

Puzzle 1:  Oddity 
困惑1 : 奇數。

 

下面的isOdd(int i)方法是用來判斷i是否是一個奇數。有沒用啊。請看:

public static boolean isOdd(int i) {

    return i % 2 == 1;

}

Solution 1: Oddity  (奇數)
解決方案1: 奇數

奇數的定義是:被2除餘1的整數。連火星人都知道,運算式: i % 2 是用來計算i被2除所得餘數,你會說來上面那個代碼不是挺好嗎。其實不是

,或者說效果不是很好。這段代碼有四分之一的情況要返回一個錯誤的結果。

為什麼是四分之一。

因為二分之一的整數是負數,二分之一的整數是正數。而上面這個 isOdd(int i) 方法,當i是負數的時候就運行不正確了。如果i是負數,無

論i是負奇數還是負偶數,這個方法都是返回 false 。

下面是一個關於Java求餘運算子(%)的判定式。

求餘運算子(%)是從這個式子反推出來的(其中a是整數,b是非零整數):

(a / b) * b + (a % b) == a

也就是說 % 運算滿足這個條件:如果a除以b,商乘以b,再加上 a % b 的值,最終結果必須等於a。

這個式子不僅非常合理,而且是剛好用到了Java中的整除運算子。
從這個判定式還能推出:當求餘運算得到一個非零結果c的時候,求餘運算子(%)左邊的數a和這個結果c應該是同符號(同為正數,或者同為負

數,或者零)。

上面的 isOdd(int i) 方法和當中所謂的“奇數”都是假定求餘運算所得的值都是正數。雖然這個假設適用於一部分情況,但是Java中的求餘

運算是和她的整除是完美統一的,而Java中的整除並沒有限定整數的符號。

如果isOdd(int i)方法中的 i 是一個負奇數,i % 2 結果應該是 -1 而不是 1 ,這時候 isOdd(int i) 返回的就是一個錯誤的結果:false。

為了避免這種錯誤,應該在代碼寫好之後用各種數字(整數,負數,零)來完整測試你的代碼。

這個 isOdd(int i) 方法存在的問題很容易搞定。只要判斷 i % 2 是不是等於零。

public static boolean isOdd(int i) {

    return i % 2 != 0;

}

如果你要在一個效能要求很苛刻的環境中使用 isOdd(int i) 方法的話,使用“邏輯與”運算子(&)來取代求餘運算子(%)會更好一些:

public static boolean isOdd(int i) {

    return (i & 1) != 0;

}


第二種版本運行起來一般會比第一種版本快。至於快多少取決於你的虛擬機器,總不可能會比第一版慢吧。一般規律都是:除法運算和求餘運算

都比其他的算術運算和邏輯運算速度慢(CPU都是做加法運算的。乘法不用做太多轉換,相當於幾個加法。)。時時刻刻都想著最佳化代碼並不是

好事,別人會看不懂你寫的代碼。我們這個例子比較好,第二個快的版本和第一版都比較易讀,因此沒理由還使用第一版。

最後概括一下好不。

1.當你使用求餘運算的時候記得多考慮運算數和結果的符號。
2.當運算數都是非負數的時候,求餘運算代碼的執行動作都是很明顯;但是如果有些數字是負數的時候代碼的執行就不是那麼明顯了。


goddie:

看不慣國產的垃圾翻譯,很多經典都被糟蹋了。完全是翻譯來好玩,如果你覺得有誤人子弟的地方請務必通知我: goddie2046@gmail.com

------------------------------

 

完成  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.