01. december 2003 - 13:13Der er
28 kommentarer og 1 løsning
Java-kalender 2
Jeg er gang med at lave et Java-program der undersøger hvilken ugedag en bestemt dato er (uden at bruge diverse indbyggede Calender-funktioner o.lign). Men jeg får nogle fejl med denne kode:
GregorCalculations.java ----------------------- public class GregorCalculations { static final int[][] monthLengths = {{31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31}};
static int leapYear(int year) { int isLeapYear = 0;
static public int daysSince1_jan_1(int year, int month, int day) { return (day + days_monthCounter(month) + days_PrevYears(year)); } }
Gregor.java ----------- public class Gregor { static public String dayOfWeek(int year, int month, int day) //throws Exception (ikke lavet endnu) { String[] weekDays = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
int weekDayNumber = GregorCalculations.daysSince1_jan_1(year,month,day) % 7; String weekDay = weekDays[weekDayNumber];
return weekDay; } }
GregorTest.java --------------- class GregorTest { public static void main(String[] args) { System.out.println(Gregor.dayOfWeek(1,1,1)); System.out.println(Gregor.dayOfWeek(2003,11,29)); System.out.println(Gregor.dayOfWeek(2003,11,30)); System.out.println(Gregor.dayOfWeek(2004,4,1)); System.out.println(Gregor.dayOfWeek(2004,2,29)); } }
Men jeg får denne fejl:
C:\Java>javac Gregor.java .\GregorCalculations.java:24: cannot resolve symbol symbol : variable year location: class GregorCalculations days_PrevMonths += monthLengths[leapYear(year)][monthCounter]; ^ 1 error
Hvad er der galt og kan det slet ikke passe at den 1. januar år 1 er en mandag?
Strengt taget går kalenderen som sådan vel tilbage til år 1. Den er først opfundet i og brugt fra 1582. Men derofr kan man vel godt regne baglæns. Eller kan man vel helelr ikke tale om år 122 f.kr..
Men jeg synes også en akademisk diskussion er sjov ;)
Jo, man kan selvfølgelig extrapolere en hvilken som helst kalender ud over dens grænser, og (mis)bruge værdierne. Mon der var mennesker, der på denne extrapolerede dag, som selvfølgelig har eksisteret, har følt med sig selv at det var år 1, at det var januar, og at det var den første i denne måned, og at det så oven i købet var mandag? ;) Det tror jeg ikke ...
erikjakobsen -> Denne sætning days_PrevYears += yearCounter * days_monthCounter(monthLengths.length); .. fandt jeg også ud af er forkert. Den skal bare hedde days_PrevYears += days_monthCounter(year, monthLengths.length); (det ekstra argument fordi year jo som du sagde før ikke blev fundet i days_monthCounter()
Det andet argument har resultatet 12 (dvs. 12 måneder pr. år). For-løkken kører altså 12 gange og optæller antallet af dage på de 12 måneder. Men som du siger kan dette vel bare optimeres til at man skriver enten 365 eller 366 dage. Der er dog stadig brug for en monthCounter til at finde antallet af dage der er i de tidligere måneder som ligger i samme år. Til sidst adderer jeg nemlig antallet af dage med antallet af dage i årets tidligere måneder som så adderes med antallet af dage i de tidligere år (helt tilbage til år 0 (eller 1582 hvis det er det man regner med :) )).
I eet tilfælde af kald til days_monthCounter vil du have måneden angivet i anden parameter med i beregningen (der hvor der står 12=monthLengths.length), og i det andet tilfælde vil du ikke, kaldet i daysSince1_jan_1. Du skal nok tage alle angivne måneder med, og trække een fra i kaldet i daysSince1_jan_1
System.out.println("Antal jan. 2003, skal være 31, giver "+days_monthCounter(2003,1)); System.out.println("Antal feb. 2003, skal være 59, giver "+days_monthCounter(2003,2)); System.out.println("Antal feb. 2004, skal være 60, giver "+days_monthCounter(2004,2)); System.out.println("Antal mar. 2004, skal være 91, giver "+days_monthCounter(2004,3)); System.out.println("Antal apr. 2004, skal være 121, giver "+days_monthCounter(2004,4)); System.out.println("Antal i aar 1, giver "+days_PrevYears(2)); System.out.println("Antal i aar 2, giver "+days_PrevYears(2));
Antal jan. 2003, skal vµre 31, giver 31 Antal feb. 2003, skal vµre 59, giver 59 Antal feb. 2004, skal vµre 60, giver 60 Antal mar. 2004, skal vµre 91, giver 91 Antal apr. 2004, skal vµre 121, giver 121 Antal i aar 1, giver 365 Antal i aar 2, giver 730
Godt set! - den kan man lede meeeget længe efter, hvis man kun kigger efter om slutresultatet er korrekt eller ej. En test direkte på days_PrevYears burde opdage den fejl noget hurtigere. (Vink: lav små tests...)
static public String dayOfWeek(int year, int month, int day) throws Exception { final int[][] monthLengths = {{31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31}};
if((year < 1 || month < 1 || month > 12 || day < 1 || day > monthLengths[leapYear(year)][month-1])) { throw new Exception("Invalid date: (" + year + "," + month + "," + day + ")"); }
int days_prevYearsMod = (year-1)/4 - (year-1)/100 + (year-1)/400;
String[] weekDays = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}; int prevDaysTotalMod = day + days_prevMonthsSameYear(year, month) + days_prevYearsMod;
return weekDays[prevDaysTotalMod % 7]; } }
Men den finder ikke de korrekte datoer. Der gemmer sig sikkert en ganske lille fejl et sted.. Nogen der kan se den? :)
Et år, der ikke er skudår bidrager med 365 dage, og 365 = 1 (mod 7) mens et skudår så giver 366 = 2 (mod 7)
For de år der kommer før skal du altså lægge 1 eller 2, og ikke 0 eller 1. Du kan måske fixe det ved også at lægge (year-1) til - men lad nu være med bare at gøre det før du ved hvad du gør.
Har du tænkt over noget med "små tests" for at se hvad der virker og hvad der ikke virker?
Erik: Du har ikke lagt et svar, men hvis du også vil have nogle point, så skriv en kommentar :)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.