2017-08-29 75 views
0

如何遞歸乾燥這段代碼以避免月份重複。遞歸DRY代碼,計算幾個月的天數,Java

我有一個想法,把1月的基本情況,並處理其他月份遞歸計算dayOfYear從上個月,然後將當前月添加到它。 類似if (month == 1) { ... } else { ... dayOfYear(month-1, dayOfMonth, year) ... } correct 但我不太確定實施情況,也不知道這是否是一種準確的方法。

假設我有一個這樣的陣列,其中,我可以存儲所有的我的日子 INT [] monthLengths =新INT [] {31,28,31,30,...,31}

public static int dayOfYear(int month, int dayOfMonth, int year) { 
if (month == 2) { 
    dayOfMonth += 31; 
} else if (month == 3) { 
    dayOfMonth += 59; 
} else if (month == 4) { 
    dayOfMonth += 90; 
} else if (month == 5) { 
    dayOfMonth += 31 + 28 + 31 + 30; 
} else if (month == 6) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31; 
} else if (month == 7) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30; 
} else if (month == 8) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31; 
} else if (month == 9) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31; 
} else if (month == 10) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30; 
} else if (month == 11) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31; 
} else if (month == 12) { 
    dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 31; 
} 
return dayOfMonth; 

}

+0

你爲什麼不只是使用API​​? –

+1

「...通過遞歸計算...」您的代碼不是遞歸的。 – Turing85

+1

爲什麼你不想僅僅創建靜態數組'int [12]'並且把所有天數放在這裏? –

回答

1

正如在其他的答案建議,你可以很容易避免遞歸只是填充年度的1天和1天的月份之間的天量陣列。 因爲從複雜性來看,遞歸將採取O(n)和預定義的陣列算法 - O(1)

但是,如果你真的想使用遞歸,您可以只需填寫的天量,一些準備陣列,通過month作爲指標使計算數組。

例如:

public static int[] daysOfMonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 

public int daysOfYear(int day, int month, int year) { 
    if (month == 0) { 
     return day; 
    } 
    //specific case for leap year 
    int leapOffset = 0; 
    if (month == 2) { 
     if (Year.of(year).isLeap()) { 
      leapOffset = 1; 
     } 
    } 
    return daysOfYear(day + daysOfMonth[month-1] + leapOffset, month - 1, year); 
} 

和測試:

@Test 
public void testDay() { 
    Assert.assertEquals(LocalDate.of(2015, Month.FEBRUARY, 25).getDayOfYear(), daysOfYear(25, 1, 2015)); 
    Assert.assertEquals(LocalDate.of(2014, Month.MARCH, 25).getDayOfYear(), daysOfYear(25, 2, 2014)); 
    Assert.assertEquals(LocalDate.of(2013, Month.MAY, 25).getDayOfYear(), daysOfYear(25, 4, 2013)); 
    Assert.assertEquals(LocalDate.of(2012, Month.JUNE, 25).getDayOfYear(), daysOfYear(25, 5, 2012)); 
} 
0

您可以使用數組映射月份到天數之和,然後根據年份添加偏移量。

private static int[] daysTillMonth = ... 

public static int dayOfYear(int month, int dayOfMonth, int year) { 
    return daysTillMonth[month] + dayOfMonth + month>1?yearOffset(year):0; 
} 

private int yearOffset(int year) { 
    // implement 
} 

你也可以撰寫的數學方程式纔算此例如:

public static int dayOfYear(int month, int dayOfMonth, int year) { 
    int n1 = (275 * month/9) 
    int n2 = ((month + 9)/12) 
    int n3 = (1 + ((year - 4 * (year/4) + 2)/3)) 
    int n = n1 - (n2 * n3) + dayOfMonth - 30 
    return n; 
} 
+0

我會嘗試這種方法,你有什麼想法如何按照我的約定來實現它。 「我有一個想法,把1月的基本情況,並處理其他月份遞歸計算dayOfYear從上個月,然後將當前的月份添加到它。「 –

0

您的代碼將在幾個方面失敗...

二月並不總是有28天...

你需要學習使用Java爲你開發的API!

在另一方面

...沒有什麼在你發佈的代碼,以遞歸關係......你甚至需要這樣......

我的建議有云:

public static long dayOfYear(int month, int dayOfMonth, int year) { 
    return ChronoUnit.DAYS.between(LocalDate.now(), LocalDate.of(year, month, dayOfMonth)); 
} 
+0

這不是關於API,問題來自我目前正在閱讀的書。 是的,你是對的,我們遇到了一個神奇的數字,與二月。 –

0

你可以初始化第二陣列:

private static int[] monthLengths = new int[] { 31, 28, 31, 30, ..., 31}; 
private static int[] monthStart = new int[12]; 
static { 
    for (int i = 1; i < monthStart.length; ++i) { 
     monthStart[i] = monthStart[i-1] + monthLength[i-1]; 
    } 
}