ich würde gerne einen Jubiläumsrechner gestalten.
Diesem gibt man ein Datum eines bestimmten Ereignisses und ein Datum bis wohin man Jubiläen ausrechnen möchte.
Anschließend rechnet er alle Jubiläen des Tages x von heute bis Tag y aus.
Das kann dann so aussehen (Auszug aus einem anderen bereits vorhandenen Windows Programm):
Er zählt nun für die Angaben Sekunden, Minuten, Stunden, Tage, Wochen, Monate und Jahre jeweils Ereignisse aus.
Am Beispiel von Sekunden möchte ich versuchen das ganze einmal zu generieren:
Er zeigt nun alle Zahlen an, die Schnapszahlen sind oder wo die gesamte Zahl Glatt ist und auf Nullen endet (Ausnahme Komma 5).
Also ich meine:
Mal so als Beispiel, ich hoffe man versteht, worauf ich hinaus möchte.
habe bereits ein größeres Projekt mit Interface dazu generiert, aber der entscheidende Code ist mir noch nicht gelungen.
Der Einfachheit halber Poste ich mal erstmal nur das relevante.
Also in der Berechnungsmethode habe ich das hier:
Calendar heute = Calendar.getInstance();
Calendar until = zeitEnde.dorZeit.getGregKalender();
long zaehler = heute.getTimeInMillis()/1000;
long vergangen = zaehler - jubilaeumszeit.getTimeInMillis()/1000;
System.out.println("Vergangen: "+vergangen);
System.out.println("Heute: "+zaehler);
System.out.println("Bis: "+until.getTimeInMillis()/1000);```
die ersten drei Zeilen sind einfache Kalender die ich erschaffen habe die die Zeit in Unixsekunden zurückgibt.
` jubilaeumszeit` gibt den Zeitpunkt des Jubiläums zurück.
` heute` ist der Zeitpunkt beim Ausführen des Projekts.
` until` gibt den Zeitpunkt bis wohin berechnet wird zurück.
Ich gebe dann also schon einmal als Beispiele in der Konsole aus, wie viel Zeit bereits vergangen ist (Sekunden), wie spät es heute ist und bis wann es geht. Natürlich alles durch 1000 geteilt, weil er ja Millisekunden ausgibt.
In meinem Beispiel sind das diese Angaben:
Vergangen: 1627234
Heute: 1443376834
Bis: 1767221999
Ich beginne am 9. September wie auch in dem Bild.
Er muss also, wenn jetzt `1627234` Sekunden vergangen sind als nächstes anzeigen:
2000000, 2222222,2500000,3000000.
So weit die Theorie.
Ich habe mir nun folgende Überlegt:
Ich möchte den zaehler da oben als Variable benutzen die weiter noch oben zählt und in einer while-Schleife abfragen, wie lange der zaehler unter der "Deadline" ist.
Also sowas hier:
```while(zaehler<=until.getTimeInMillis()/1000) {
}```
Meine Idee wäre nun Umständlich aus Integern Strings zu machen, ihre Länge abzumessen und dann daraus neue Zahlen zu machen.
Also bei 1627234 sieht er, aha 7 Stellig, also nehme ich die erste Stelle, rechne eins drauf und hänge sechs nullen dran...
Hat jemand von euch eine ultimativ brillante Idee, wie ich das auch einfacher erhalten kann?
Das muss auch gar nicht so einen Zusammenhang mit dem Jubiläumsrechner haben, es kann sich ja auch um ein Zahlenexperiment handeln, wie man ausgehend von einer Zahl weitere glatte und Schnapszahlen macht.
Ich hoffe ihr könnt meine Worte nachvollziehen und habt vielleicht die eine oder andere Idee. :)
Gruß
Lukas
Verstehe ich das richtig, du überlegst in einer Schleife die Milisekunden bis zum 100-jährigen Jubiläum zählen? Das müssten circa 3*10^12 Iterationen sein. Naja, geht schon, aber schön ist es nicht. Wäre es in deinem Anwendungsfall nicht auch möglich die konkreten Zeitpunkte der Jubiläen auszurechnen? So à la
[tex]
jubilaeum = startzeitpunkt + x \cdot 10^y
jubilaeum = startzeitpunkt + (x+0.5) \cdot 10^y
jubilaeum = startzeitpunkt + x \cdot \frac{10}{9} \cdot 10^y
jubilaeum = …
x \in {1, …, 9},
y \in {0, …, \infty }
[/tex]
Da bräuchte man sich dann gar nicht erst um irgendwelche Überprüfungen zu kümmern.
PS: Wenn ich mir alle paar Minuten anhören müsste: „Schatz, wir sind jetzt 700 Minuten Minuten zusammen!“, „Schatz, wir sind jetzt 777 Minuten zusammen!“, „Schatz, wir sind jetzt 800 Minuten zusammen“ etc. - dann würde es kein 900-minütiges Jubiläum mehr geben… :livid:
vielen dank für Deine Antwort.
Also zum Nachsatz: Natürlich, klar. das ist auch Unfug. Ich hatte nur extra ein Kurzfristiges Beispiel (vom 9. September 15 bis gestern) genommen, wo es ja mathematisch betrachtet Unmengen Ereignisse gibt. So kann ich beim Programmieren viel mehr Ergebnisse zum Vergleichen nutzen.
Wenn man aber schon 20 Jahre zusammen ist oder ein 20jähriges Jubiläum wegen irgendetwas feiert, dann gibt die Liste höchstens 2-3 Ereignisse aus. Das ist dann immer schön zu begehen. Mache ich schon länger so.
Zum Programmiertechnischen:
Um Napoléons Willen, ne, ich wollte keine 3*10^12 Iterationen erreichen.
Die while-Schleife hatte einen anderen Zweck.
Ich wollte mir die aktuelle Zahl die vergangen ist ausgeben lassen, zum Beispiel 1627234, dann daraus resultierend die nächste Verfügbare Zahl. Und das gehe ich dann so lange in While durch, bis die nächste gebildete Zahl nach obigen Kriterien noch im Zeitfenster drin vorkommt. Hab ich aber bisher für viel zu umständlich gehalten.
=========
Also, ich hab’s geschafft, die Sekunden laufen.
Der Rest sollte ja eigentlich genauso funktionieren.
Schaut mal, der Code geht folgendermaßen:
Calendar jubilaeumsCal = zeitAnfang.dorZeit.getGregKalender();
Calendar heute = Calendar.getInstance();
Calendar until = zeitEnde.dorZeit.getGregKalender();
long jubilaeumszeit = jubilaeumsCal.getTimeInMillis()/1000;
long heuteLong = heute.getTimeInMillis()/1000;
long vergangen = heuteLong - jubilaeumsCal.getTimeInMillis()/1000;
long deadLine = until.getTimeInMillis()/1000;
System.out.println("Vergangen: "+vergangen);
System.out.println("Heute: "+heuteLong);
System.out.println("Bis: "+until.getTimeInMillis()/1000);
String numStr = String.valueOf(vergangen);
int anz = numStr.length();
int first = Character.getNumericValue(numStr.charAt(0));
boolean durchlauf = true;
while(durchlauf) {
long schnaps1 = first*(long)Math.pow(10,anz-1);
long schnaps2 = (long)((first+0.5)*(long)Math.pow(10,anz-1));
long schnaps3 = (long)(first*(10.0/9)*(long)Math.pow(10,anz-1));
if(schnaps1+jubilaeumszeit<=deadLine) {
System.out.println(schnaps1+" am: "+(schnaps1+jubilaeumszeit));
} else {
durchlauf = false;
}
if(schnaps2+jubilaeumszeit<=deadLine) {
System.out.println(schnaps2+" am: "+(schnaps2+jubilaeumszeit));
} else {
durchlauf = false;
}
if(schnaps3+jubilaeumszeit<=deadLine) {
System.out.println(schnaps3+" am: "+(schnaps3+jubilaeumszeit));
} else {
durchlauf = false;
}
first++;
if(first==10) {
first = 1;
anz++;
}
}
}```
Ich hab einen boolean durchlauf und die while-Schleife läuft solange, wie dieser true ist.
Anfangs bestimme ich von der aktuellen Zahl an vergangenen Sekunden die Länge der Zahl und ihre erste Ziffer.
Dann bilde ich nach den von Dow_Jones aufgezeigten Rechenregeln die drei Jubiläen pro Anfangsziffer.
Also 2; 2,2222 und 2,5 als Beispiel.
Mir fällt gerade auf, dass die alle Schnaps heißen, obwohl nur eins Schnapszahl ist. Egal. Lasst euch nicht verwirren.
Dann überprüft er, ob das, zuzüglich der Jubiläumszeit, also der Zeit wann der Startpunkt war noch vor dem Deadlinedatum ist.
Wenn ja, dann gibt er es aus, wenn nicht, wird der Durchlauf gestoppt.
Anschließend wird die Zahl ganz vorne um eins erhöht. Wenn sie 10 erreicht, wird stattdessen die Länge erhöht.
Warum stoppe ich nicht gleich und nutze einen boolean dafür?
Das hat den Hintergrund, dass die Schnapszahl keine genaue Position in der "Rangordnung" hat.
Also zwei Beispiele:
30.000
33.333
35.000
(hier ist die Schnapszahl vor der ,5-Zahl)
60.000
66.666
65.000
(hier sit die Schnapszahl hinter der ,5-Zahl)
Funktioniert so weit.
Ob das Effektiv ist, ist eine andere Frage.
Was haltet ihr von dieser Rechnung?
Mal ganz allgemein, wie ich das angehen würde: Die verschiedenen Arten von Jubiläen würde ich in irgend einer Form als unendliche Folgen modellieren, am einfachsten als Iterator (ein weiterer Kandidat wäre java.util.Stream). Dann würde ich einen Wrapper schreiben, der jeweils einen Iterator und sein aktuell nächstes Element beinhaltet. Das kommt dann in eine PriorityQueue, so dass ich mir ganz leicht den kleinsten Iterator rausfischen kann, mir den Wert hole und den Iterator-Wrapper “eins weitergedreht” wieder in die Queue packe. Dann kann ich solange iterieren, wie ich will, meine Ergebnisse kommen immer “just in time” sortiert.
Mal ein Beispiel mit zwei Arten von Jubiläen (Fünfer und Schnapszahlen), aber man kann in die Queue beliebig viele hineinstopfen:
import java.util.Iterator;
import java.util.PriorityQueue;
public class Jubilaeum implements Iterable<Integer> {
private Iterator<Integer> byFive = new Iterator<Integer>() {
private int base = 1;
private int value = 1;
@Override
public boolean hasNext() {
return true;
}
@Override
public Integer next() {
int result = 5 * base * value;
if (value == 20) {
value = 3;
base *= 10;
} else {
value++;
}
return result;
}
};
private Iterator<Integer> repUnit = new Iterator<Integer>() {
private int base = 100;
private int digit = 1;
@Override
public boolean hasNext() {
return true;
}
@Override
public Integer next() {
int result = (base - 1) / 9 * digit;
if (digit == 9) {
base *= 10;
digit = 1;
} else {
digit++;
}
return result;
}
};
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private PriorityQueue<Pair> queue = new PriorityQueue<>();
{
queue.add(new Pair(byFive));
queue.add(new Pair(repUnit));
}
@Override
public boolean hasNext() {
return true;
}
@Override
public Integer next() {
Pair pair = queue.poll();
queue.add(pair.step());
return pair.next;
}
};
}
private static class Pair implements Comparable<Pair> {
private final int next;
private final Iterator<Integer> iterator;
private Pair(Iterator<Integer> iterator) {
this.next = iterator.next();
this.iterator = iterator;
}
private Pair step() {
return new Pair(iterator);
}
@Override
public int compareTo(Pair o) {
return Integer.compare(next, o.next);
}
}
public static void main(String[] args) {
for (int value : new Jubilaeum()) {
System.out.println(value);
if (value > 10000) break;
}
}
}
Die Technik mit der PriorityQueue sollte man kennen, damit lassen sich auch ernsthaftere Probleme recht elegant lösen.
ich danke vielmals für Deine Antwort. Eine sehr interessante Anregung ist das. Ich werde mich einmal näher mit der Sache beschäftigen.
Ich hab dazu mal ein paar kleine Fragen des Verständnisses.
1)
Mal ein Beispiel mit zwei Arten von Jubiläen (Fünfer und Schnapszahlen), aber man kann in die Queue beliebig viele hineinstopfen
Wen Du hier mit 5 rechnest, dann sind das ja auch schon alle drei Dinge, die ich haben wollte, oder? Weil bedingt durch die Teilbarkeit durch 5 deckt das ja auch schon die auf 000000 endenden ab, richtig? (kleine Verständnisfrage ;))
Du generierst da Zahlen von 0 bis 10.000, wobei die 10.000 ja ganz unten verändert werden können.
Ich rechne Zahlen zwischen a und b aus. Die obere Schrank b kann ich also da unten übergeben.
Ich habe aber noch nicht richtig verstanden, wie ich das dann mit Wert a mache.
Also dass er weiß, aha ich beginne aber bei 11.484 und er soll da weiterrechnen.
Nur als Beispiel.
Ich übergebe beim Generieren also beispielsweise den Parameter long anfangswert.
Kannst Du mir bittenoch einmal erläutern, wie ich das in den Iterator einpflegen kann?
Ansonsten hab ich das erstmal verstanden. Ich schaue mir Iterator und PriorityQueue nochmal genauer an.
ich muss gestehen dass ich nicht sehr viel gelesen habe, aber warum benutzt du nicht die neue Java8 Date API, das arbeiten mit Kalender und umrechnen ist doch umständlich ?!
ich danke vielmals für Deine Antwort. Eine sehr interessante Anregung ist das. Ich werde mich einmal näher mit der Sache beschäftigen.
Ich hab dazu mal ein paar kleine Fragen des Verständnisses.
1)
Wen Du hier mit 5 rechnest, dann sind das ja auch schon alle drei Dinge, die ich haben wollte, oder? Weil bedingt durch die Teilbarkeit durch 5 deckt das ja auch schon die auf 000000 endenden ab, richtig? (kleine Verständnisfrage ;))
Du generierst da Zahlen von 0 bis 10.000, wobei die 10.000 ja ganz unten verändert werden können.
Ich rechne Zahlen zwischen a und b aus. Die obere Schrank b kann ich also da unten übergeben.
Ich habe aber noch nicht richtig verstanden, wie ich das dann mit Wert a mache.
Also dass er weiß, aha ich beginne aber bei 11.484 und er soll da weiterrechnen.
Nur als Beispiel.
Ich übergebe beim Generieren also beispielsweise den Parameter long anfangswert.
Kannst Du mir bittenoch einmal erläutern, wie ich das in den Iterator einpflegen kann?
Ansonsten hab ich das erstmal verstanden. Ich schaue mir Iterator und PriorityQueue nochmal genauer an.
Gruß
Lukas[/QUOTE]
Hallöle,
hat noch jemand Antworten auf meine zwei gestellten Fragen? Die Behandlung selbiger geht mir leider noch nicht ganz in den Kopf.
{
if (value < 8000) continue;
System.out.println(value);
if (value > 10000) break;
}
wäre die direkteste Variante, wobei das nur in der Verwendung stattfindet
könnte auch in der next()-Methode (die mit dem poll()) stehen,
dort den Wert prüfen, wenn zu klein dann wieder next() aufrufen, wobei Gefahr von StackTrace-Exception bei mehr als 1000 Schritten,
auch dort eine Schleife wäre schonender
edit:
pro Zehner-Potenz kommen auch nur 27 Werte dazu (9 0er, 9 5er, 9 xer), auf Long umgestellt sind keine 500 zu organisieren,
sie auf diese Weise zu berechnen statt mit Formeln ist eine Art Eleganz, für kompliziertere Fälle gut zu wissen,
wobei hier auch noch gut möglich wäre mit den einmal gefundenen Varianten die der nächst höheren Stufe mit Anhängen von 0en und Ziffern zu bestimmen,
aber man könnte sie jedenfalls nach einmaligen Erstellen in ein Array packen,
dann alle normalen Möglichkeiten des Durchlaufs, Prüfung mit Min-Wert usw.
ich danke vielmals für Deine Antwort. Continue ist das Zauberwort. Habe ewig danach gesucht. Muss mich mehr mit solch Schleifenbegriffen auseinandersetzen.
Nun funktioniert es. Ich danke nicht nur für den letzten Tipp zu meinem Projekt. Ich danke viel eher für den Begriff Iterator. Ist mir bei meinen vielen Java-“Fortbildungen” noch nie begegnet, aber scheint extrem praktisch zu sein, da fallen mir spontan schon ganz andere Projekt zu ein…
Dann schau dir auch Iterable an. Damit kannst du über Objekte deiner eigenen Klassen in erweiterten For-Schleifen (oder „For-Each-Schleifen“, jedenfalls die mit dem Doppelpunkt) iterieren.