Hi!
Ich versuche, eine While schleife zu programmieren, die so oft
durchläuft bis zwei dreistellige Vektoren vom Typ double gleich sind.
Dazu habe ich die Bedinung so formuliert:
while (r[0] != v[0] || r[1] != v[1] || r[2] != v[2])
{
.....
}
Alle drei Komponenten müssen gleich sein.
Lass ich mir bei jedem Schleifendurchlauf beide Vektoren ausgeben, sind
die auf die angezeigte Stellenanzahl bereits gleich, leider bricht die
Schleife nicht ab.
Wie schaffe ich das, den Vergleich nur auf 6 Nachkommastellen genau
anstellen zu lassen?
Vielen Dank für die Hilfe,
Grüße.
Patrick
Ach ja, wenn ich alle Variablen als float deklariere, dann bricht die
Schleife korrekt ab, die letzten Stellen sind aber zu ungenau.
Ich brauche die 6 Nachkommastellen.
Patrick schrieb:> Wie schaffe ich das, den Vergleich nur auf 6 Nachkommastellen genau> anstellen zu lassen?
Double oder Float auf Gleichheit zu prüfen ist nicht so toll.
Wie du schon gemerkt hast brauchst du eine kleine Abweichung, bei der du
sagen kannst "und jetzt sind die Zahlen für praktische Zwecke gleich".
Am besten geht sowas über ein Intevall, z,b so
>Äh mist, Tausche || durch && , an der Stelle hab ich nur probiert, ob
vllt. irgendeine der Komponenten ausreichend gleich wird.
Huch? Für diese Beschreibung:
>eine While schleife zu programmieren, die so oft>durchläuft bis zwei dreistellige Vektoren vom Typ double gleich sind
ist diese Formulierung durchaus angemessen.
1
while(r[0]!=v[0]||r[1]!=v[1]||r[2]!=v[2])
2
{
3
.....
4
}
Falls die || durch && ersetzt werden, dann bricht die Schleife ab sobald
eine der Vektorspalten gleich ist.
Aber Dein eigentliches Problem ist, das Du double Werte eben nur mit
begrenzter Genauigkeit berechnen kannst und deswegen auch vergleichen.
D.h. ein mathematischer Zusammenhang kann zwar eine Identität
beschreiben, die tatsächliche Berechnung aber eben doch verschiedene
Zahlen ergeben.
Es wäre gut, wenn Du mal den Anwendungsfall beschreibst.
Eine allgemeine Empfehlung wäre die Bedingung der Gleichheit dadurch zu
ersetzen, das die Werte sich um mehr als ein gewisses Epsilon
voneinander unterscheiden müssen um als ungleich bewertet zu werden.
Floh schrieb:> //Funktion abs liefert absoluten Betrag> const float intervall=0.01;>> float a,b;> //irgendwie besetzen>> if( abs(a-b) < intervall)> ...>> //falls a und b auf 0.01 gleich
So hab ichs jetzt gemacht, funktioniert wunderbar :D
Vielen Dank für den Tipp!
Stand ich jetzt wirklich auf dem Schlauch :D
Wirklich? || statt && ? Aber && wird doch nur "true" wenn alle drei
Bedingungen erfüllt sind? Oder hab ichs vertauscht?
Der Anwendungsfall ist zu einer 3x3 Matrix einen stationären Vektor zu
finden. Ist eine Übungsaufgabe für die Uni, deswegen hab ich den ganzen
Code nicht reingestellt ;)
Also durch wiederholtes ausführen von r= M*r (mit M = Matrix, r=Vektor),
bis sich r nicht mehr ändert.
Gibt wahrscheinlich eine geschicktere Lösung als meine, ist etwas
länglicher geworden - naja - übung macht den Meister.
Danke für die Hilfe!
Patrick schrieb:> Aber && wird doch nur "true" wenn alle drei> Bedingungen erfüllt sind?
genauso isses,
aber du willst ja die Schleife solange ausführen lassen, solange noch
eine Komponente nicht gleich,
also solange x1!=x2 oder y1!=y2 oder z1!=z2
und oder ist nun mal ||
>Wirklich? || statt && ? Aber && wird doch nur "true" wenn alle drei>Bedingungen erfüllt sind? Oder hab ichs vertauscht?
Lassen wir mal das Epsilon weg und nehmen den ursprünglichen Code:
1
while(r[0]!=v[0]||r[1]!=v[1]||r[2]!=v[2])
2
{
3
.....
4
}
Du hast geschrieben, dass : "...While schleife zu programmieren, die so
oft
durchläuft bis zwei dreistellige Vektoren vom Typ double gleich sind."
In der obigen Formulierung wird die Schleife solange wiederholt, wie nur
irgendeines der r[n] != v[n]. D.h. umgekehrt, erst wenn alle r[n] ==
v[n], dann bricht die Schleife ab.
Ersetzt Du aber die || durch &&,:
1
while(r[0]!=v[0]&&r[1]!=v[1]&&r[2]!=v[2])
2
{
3
.....
4
}
Dann läuft die Schleife nur solange wie alle r[n] != v[n]. Sobald nur
irgendeines der r[n] = v[n] ist bricht die Schleife ab. Das aber stimmt
nicht mit der obigen Forderung überein.
>Aber && wird doch nur "true" wenn alle drei>Bedingungen erfüllt sind
Das ist aber hier noch in Beziehung zu setzen mit der Wirkung der
Bedingung des while-Befehles. Der läuft nämlich solange die Bedingung
wahr ist. Da aber erst der Schleifenkörper den Wunschzustand herstellt
muss die Schleife ausgeführt werden solange der Wunschzustand nicht
besteht. Der Wunschzustand besteht aber nicht, wenn irgendeiner der r[n]
!= v[n], was vollständig eben so: "(r[0] != v[0] || r[1] != v[1] ||
r[2] != v[2])" ausgedrückst wird.
Floh schrieb:> Patrick schrieb:>> Wie schaffe ich das, den Vergleich nur auf 6 Nachkommastellen genau>> anstellen zu lassen?>> Double oder Float auf Gleichheit zu prüfen ist nicht so toll.> Wie du schon gemerkt hast brauchst du eine kleine Abweichung, bei der du> sagen kannst "und jetzt sind die Zahlen für praktische Zwecke gleich".>> Am besten geht sowas über ein Intevall, z,b so>>
1
>//Funktion abs liefert absoluten Betrag
2
>constfloatintervall=0.01;
3
>
4
>floata,b;
5
>//irgendwie besetzen
6
>
7
>if(abs(a-b)<intervall)
8
>...
9
>
10
>//falls a und b auf 0.01 gleich
11
>
12
>
> :-)
abs() liefert aber nur einen Absolutbetrag einer ganzen Zahl,
in diesem Fall also komplett ohne Nachkommastellen.
Du meinst wohl fabs()?
Außerdem will er doch double vergleichen.
Dann könnte man intervall auch gleich double machen, es wird
ja ohnehin zu double konvertiert.
Patrick schrieb:> Gibt wahrscheinlich eine geschicktere Lösung als meine
Wenn sie das Problem in ausreichender zeit löst wieso nicht? Ich würde
aber in so einem Fall noch eine maximale Iterationszahl vorsehen, z.B.
nach 100'000 Durchläufen abbrechen, und dann den User darauf hinweisen
das abgebrochen wurde und das Ergebnis ggf. nicht verlässlich/genau ist
das ist besser als wenn das Programm sich "aufhängt" (gerade zum
testen).
Das deckt dann auch den Fall ab, das es ggf. gar keine Lösung gibt, oder
die Lösung numerisch instabil ist.
Klaus Wachtler schrieb:> Du meinst wohl fabs()?
Wahrscheinlich :-)
So Sachen schreib ich eigentlich immer kurz in mein Programm rein, geht
schneller als nach der include zu suchen :-)
Patrick schrieb:> while (r[0] != v[0] || r[1] != v[1] || r[2] != v[2])
Man darf das auch so formulieren, evtl. verständlicher:
while (!(r[0] == v[0] && r[1] == v[1] && r[2] == v[2]))
Hi !
Also irgendwie gibt es bei dem Programm doch Probleme.
Ich habe jetzt das gleiche Problem mit einem Lösungsansatz über "for"
schleifen geschrieben.
Dieser schafft den Abbruch mit der gleichen Bedingung wie oben, bzw. der
verbesserten: !(r[0] == v[0] && r[1] == v[1] && r[2] == v[2]) .
Hatte da wirklich nen Denkfehler, || war schon richtig, && hatte ich zum
testen genommen.
Irgendwas stimmt an meinem ersten Programm nicht, und ich würde wirklich
gerne wissen was.
Hätte jemand mal Zeit und Lust, über die paar Zeilen drüberzuschauen?
Leider müsste ich das per e-mail verschicken, sonst gibts bei der Abgabe
u.U. probleme wie "du hast es ja aus dem Netz gezogen".
Ansonsten hab ich ja jetzt eine funktionierende Lösung. Mir gefällt zwar
die while schleife besser, aber das for ist auch o.k.
Danke und viele Grüße,
Patrick
Patrick schrieb:> Hätte jemand mal Zeit und Lust, über die paar Zeilen drüberzuschauen?> Leider müsste ich das per e-mail verschicken, sonst gibts bei der Abgabe> u.U. probleme wie "du hast es ja aus dem Netz gezogen".>>> Ansonsten hab ich ja jetzt eine funktionierende Lösung. Mir gefällt zwar> die while schleife besser, aber das for ist auch o.k.
Naja, in C zumindest sind for und while äquivalent.
for ist nur eine Abkürzung für while!
Die Abbruchbedingung ist entscheidend, und wenn Du die hast, so kommst
Du sowohl aus der while wie auch aus der for Schleife immer raus.
Gerry E. schrieb:> Patrick schrieb:> Die Abbruchbedingung ist entscheidend, und wenn Du die hast, so kommst> Du sowohl aus der while wie auch aus der for Schleife immer raus.
Angesichts der Schwierigkeiten, die der TO damit hatte, zu entscheiden
ob && oder ||, aber auch aus allgemeinen Überlegungen heraus, müsste man
eigentlich, zumindest gegenüber Anfängern, eher vermeiden von
"Abbruchbedingungen" zu sprechen, denn die Bedingung in for oder
while-Schleifen sorgt gerade dann dafür, dass die Schleifer weiter
bzw. nochmals durchlaufen wird, wenn sie wahr ist.
Hingegen scheint es mir einleuchtend zu sein wenn man intuitiv annimt,
dass "Abbruchbedingungen" wahr sein müssen, damit sie eine Abbruch, hier
also ein Verlassen der Schleife bewirken.
Hoffe das ist hilfreich.
So jetzt hab ich das Pwd. wieder:
Also ich wollte das ja nicht öffentlich hier reinschreiben, wegen der
Abgabe, deswegen hatte ich den Vorschlag mit der e-mail gemacht. Die
sind recht hart, was Plagiatsfälle betrifft.
Ich werde jetzt die sowieso funktionierende Lösung abgeben, deswegen
häng ich die nicht funktionsfähige while-Lösung mal an, damit Google das
auch nicht gleich findet.
Hoffe, ich hab das ausreichend kommentiert.
Es sind noch viele "Testausgaben" mit eingebaut (dementsprechend
Markiert) die das ganze noch etwas länger aussehen lassen als es ist.
Hoffe jemand findet meinen Fehler :D
Vielen Dank fürs helfen!
Patrick
EDIT: Ich kann nichts hochladen? Dann eben hier :
http://nopaste.info/e78cc3b7a2.html
Huch schrieb:> ... eher vermeiden von "Abbruchbedingungen" zu sprechen ...
Stimmt irgendwo - habe ich mir noch nie überlegt, daß man
damit Probleme haben kann.
Weisst Du Patrick, Deine Fehler im Programm musst Du Dir schon selber
suchen. Das sind ja die inhärenten Annahmen, das Du nicht nur Programme
schreibst sondern auch Fehler suchst, Deinen Entwurf mit dem
tatsächlichen Verhalten vergleichst uswusf.
Bei deinem ersten Posting war halt jedem Praktiker klar das Vergleich
von double-Variablen so Tücken hat. An sich hättest Du durch
analytisches (wissenschaftliches) selbst darauf kommen müssen das ein
einzelner Vergleich hier schief geht obwohl die Zahlenwerte gleich sein
"sollten". Wenn Du an dieser Stelle nachgefragt hättest wäre unsere
plausible Vermutung vorweggenommen, aber mehr Eigeninitiative von Dir
gezeigt.
Ein weitere analytischer Schritt wäre gewesen, festzustellen, ob zwei
Werte von denen Du annimmst, das sie identisch sind, auch auf anderem
Weg als mit dem "==" bzw. "!=" als identisch zu beurteilen sind. Dann
hättest Du festgestellt, das es gewisse Abweichungen im Bitmuster gibt,
obwohl die Ausgabe innerhalb von 6 Stellen nach dem Komma identisch ist
(oder auch nicht).
Das hätte Dich zu der obigen These geführt, das eine mathematische
Identität, praktisch ausgeführt dennoch zu unterschiedlichen Resultaten
führen kann. Das aber zu Rundungsproblemen, Zahlendarstellung etc.
So! Abgesehen davon, das Du ausser "geht nicht" garnicht geschrieben
hast, was das Problem ist, ist es gerade das was Du im Studium lernen
sollst. Analytisches Arbeiten, folgerichtiges Denken.
Mach das mal selbst. Ich übe selber noch.
Aha.
Herzlichen Dank auch für diese Belehrung. Meine Studienziele waren mir
noch nie so klar. Was soll denn so eine arrogante Art?
Statt jetzt einfach das funktionierende abzugeben und es dabei zu
belassen bastel ich trotzdem weiter an dem alten rum, weil ich nicht
verstehe warum das auf diesem weg nicht funktioniert.
Und du hast sicher nie irgendjemanden gefragt, als du noch am Anfang
standest und irgendwas nicht funktioniert hat? Alles immer nur
selfmade-Männer hier in diesem Forum. War doch ein Fehler, hier zu
fragen.
Mir ist völlig bewusst, warum ich bei dieser Annährung mit dem direkten
Vergleich von double auf Probleme stoße. War es mir auch schon vorher.
Ich meine, zwei verschiedene Lösungsansätze zu schreiben, von denen
einer zum Erfolg führt und der andere nur knapp, ist prinzipiell schon
mindestens mit "ausreichend" an Eigeninitiative zu bewerten.
Mit der gleich definierten Bedingung funktioniert das eine, aber das
andere nicht, obwohl es zwischen for und while keinen ersichtlichen
Unterschied gibt.
Ich habe nicht gesagt "funzt nicht", sondern mein Problem ist klipp und
klar formuliert: Er geht nicht aus der while schleife, obwohl er die
gleiche Bedingung bei FOR akzeptiert.
Warum funktioniert das bei for, und nicht bei while?
Falls mir doch noch jemand weiterhelfen kann, wäre ich weiterhin
dankbar. Sollte noch irgendjemand den Drang verspüren seine
Hobbypädagogik an den Mann zu bringen, mein Bedarf ist gedeckt!
Ich bedaure Dich, ohne Deine ausdrückliche Aufforderung über Denk- und
Arbeitsweise bzw. Art der Frageformulierung sowie die Situation belehrt
zu haben. Ich hoffe Du verzeihst mir, kann jedoch auch damit leben wenn
Du es nicht tust.
Viel Erfolg noch.
Ähm,
also aus der Erfahrung heraus anderen Studenten Java und C beizubringen,
kann es eben am Anfang passieren, dass man vergisst die Laufvariable zu
in/dekrementieren. Evtl. liegt es daran. Da du ja anscheinend eine
for-Schleife nutzt (gut man kann sie auch geschickter nutzen, um ohne
Laufvariable nutzen nutzen zu müssen) und auch den selben Code innerhalb
der Schleifen hast (?), wäre es ein Blick Wert. Anders kann ich mir ohne
den Code zu sehen - und das muss man nicht unbedingt für ne Ferndiagnose
, aber hilfreich schon - nicht eklären. Und wir sind alle etwas faul...
also wäre's angebracht wenigstens den allgemein gehaltenen Pseudo-Code
für den Inhalt der Schleife (wenn er denn so geheim ist) zu posten, denn
hier hilft man sich freiwillig und nicht weil man muss.
Viel Erfolg noch!
Irgendein HiWi