2012-08-10 101 views
3

我必須在這裏做一些根本性的錯誤。我有非常簡單的代碼:Java:基本數學錯誤?

private static final long MILLIS_PER_YEAR = 1000 * 60 * 60 * 24 * 365; 

//... 

public long getAge() { 
    long millis = System.currentTimeMillis() - this.getBirthdate().getTime(); 
    System.out.println("Computed age: " + (millis/MILLIS_PER_YEAR) + ", birthdate=" + this.getBirthdate() + ", birthdateMillis=" 
      + this.getBirthdate().getTime() + ", now=" + new Date() + ", nowMillis=" + System.currentTimeMillis() 
      + ", elapsedMillis=" + millis); 
    return millis/MILLIS_PER_YEAR; 
} 

...但它給一些完全不正確的輸出:

Computed age: 248, birthdate=2001-01-01 10:00:00.0, birthdateMillis=978307200000, now=Fri Aug 10 16:56:48 EST 2012, nowMillis=1344581808173, elapsedMillis=366274608173 
Computed age: 184, birthdate=2004-01-01 10:00:00.0, birthdateMillis=1072915200000, now=Fri Aug 10 16:56:48 EST 2012, nowMillis=1344581808173, elapsedMillis=271666608173 

如果我手動運行相同的計算(or by using Google),我得到了correct result(內由於在實際年度中有365天以上的事實,因此是合理的補貼)。

在這段代碼中,相同的數學是如何產生這種無意義的輸出的?

+1

在我的IDE'1000 * 60 * 60 * 24 * 365'帶有一個警告,這會導致溢出。 BTW一年平均有365.2425天。 – 2012-08-10 07:13:16

+0

你在用什麼IDE?我在Eclipse(Helios)中,它沒有給出警告。如果有的話,會非常有幫助。 – aroth 2012-08-10 07:16:25

+0

我使用IntelliJ CE,它在免費版本中有數百個警告,並且其中大多數都是快速修復。即使在編輯時,我也會使用快速修復,即我編寫了我知道IDE可以爲我解決的最少代碼。 ;)Intellij Ultimate(不免費)有超過700條警告,主要是修復。我有一個商業許可證,但大多數時候使用免費版本,因爲我可以一次在多個盒子上運行它。 – 2012-08-10 07:19:02

回答

13

MILLIS_PER_YEAR的值是錯誤的。它是1471228928而不是所需的31536000000

看看該值的計算:所有參與值爲int值(數字,非十進制常量爲int-默認值爲Java)。這意味着計算的結果也將是一個int的值。但所需的值大於int可以容納,所以你會有溢出。

爲了確保caluclation上long值來實現,只是讓值的至少一個長(通過附加L後綴):

private static final long MILLIS_PER_YEAR = 1000L * 60 * 60 * 24 * 365; 
+0

謝謝,明白了。我知道它必須是一些基本的東西。上一次我遇到了一個整數溢出問題的實際例子。 – aroth 2012-08-10 07:14:45