ubuntuusers.de

C++: double, Problem mit Wertebereich?

Status: Gelöst | Ubuntu-Version: Ubuntu 12.04 (Precise Pangolin)
Antworten |

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6488

Wohnort: Hamburg

Ich habe da mal wieder eine merkwürdige Erscheinung beobachtet. Normalerweise würde ich bei sowas auf einen Überlauf vermuten, aber sollte ich dann nicht auch eine Exception bekommen?

Also ich experimentiere gerade mit digitalen Filtern und jetzt sind CIC-Filter drann. Das funktioniert auch erstmal. Aber ab Filtern dritter Ordnung flippt meine Darstellung aus. Da sind dann 3 Integratorstufen hintereinander und mein Maximalwert liegt dann etwa bei 4.9e+10. Das sollte doch bei einer double Variablen auf einem 32-Bit System noch keinen Überlauf erzeugen (oder doch?). Das Programm läuft jedenfalls weiter.

Ich muss zugeben, das ich mir die Arbeit hier einfach machen wollte und deshalb bereits vorhandene Komponenten wieder verwendet habe (deswegen verwende ich double Werte).

Ich bin aber etwas verunsichert, weil ich keine Exception bekommen habe. Sowas ist mir bisher nur mit einer Division durch 0 gelungen. Ich füge mal einen Screenshot der Programmausgabe an. Da kann man dann auch sehen, das trotz des Fehlers der richtige Kurvenverlauf noch zu erahnen ist. Das Gesamtergebnis ist also zumindest wieder im Bereich des Darstellungsfensters.

Es geht mir jetzt nicht darum, wie man solche Filter richtig implementiert, sondern darum zu verstehen, was hier passiert sein könnte, da das Programm ja weiterläuft.

p.s. bei dem Tooltip fehlt leider der Mauszeiger.

Bilder

Keba Team-Icon

Ehemalige
Avatar von Keba

Anmeldungsdatum:
24. Juli 2007

Beiträge: 3802

Hallo,

Dakuan schrieb:

[…] mein Maximalwert liegt dann etwa bei 4.9e+10. Das sollte doch bei einer double Variablen auf einem 32-Bit System noch keinen Überlauf erzeugen (oder doch?).

Hm? Wikipedia sagt, die Maximalgröße liege bei 2.147.483.647. Dein Wert ist etwa 20 mal größer. Ich würde mal behaupten, da finden Überläufe statt. //Edit: Oh, ich hab deutlich zu schnell gegoogelt und den erstbesten Wert übernommen. Das war Unsinn.

Das Programm läuft jedenfalls weiter.

Solche Überläufe werfen keinen Fehler. Dein Programm rechnet dann eben mit einer entsprechenden Zahl weiter.

Grüße, Keba

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Du kannst Dir ja mal das Limit auf Deinem System ausgeben lassen: http://www.cplusplus.com/reference/limits/numeric_limits/

Und eine Exception gibt es nicht; iirc kann man aber anhand von Prozessor-Flags testen, ob es einen Überlauf gegeben hat. Musste mal googlen ☺

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6488

Wohnort: Hamburg

Und eine Exception gibt es nicht;

Ok, wieder mal zu kurz gedacht. Da werde ich dann wohl doch auf Integer/Festkomma Addition umstellen müssen, wie es in der Literatur empfohlen wird. Angeblich wird der Überlauf dann durch die nachfolgenden Stufen "repariert", sofern einige Randbedingungen eingehalten werden. Da muss ich aber erst noch herausfinden wie das geht.

Das mit den Limits ausgeben lasen habe ich noch nicht verstanden. Aber es ist ja auch schon spät, vielleicht erkenne ich das morgen früh.

Ich konnte auch noch nicht herausfinden, wie viele Bits für Exponenten und Vorzeichen reserviert werden und wie viele für die Mantisse, aber eigentlich sollte die Mantisse sogar in 24 Bit Platz haben und die FPU sollte sowieso mehr können (hat die nicht 80 Bit?). Ok, ich denke da morgen nochmal drauf nach.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Schau mal hier und dort.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

Keba schrieb:

Solche Überläufe werfen keinen Fehler. Dein Programm rechnet dann eben mit einer entsprechenden Zahl weiter.

Ja - das Motto dahinter lautet: Lieber schnell als richtig. Ist bei Java auch nicht besser.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

user unknown schrieb:

Keba schrieb:

Solche Überläufe werfen keinen Fehler. Dein Programm rechnet dann eben mit einer entsprechenden Zahl weiter.

Ja - das Motto dahinter lautet: Lieber schnell als richtig. Ist bei Java auch nicht besser.

Das liegt daran, dass beide - wie alle ernst zunehmenden Sprachen - den Standard IEEE 754 implementieren. Siehe auch:

The special values such as infinity and NaN ensure that the floating-point arithmetic is algebraically completed, such that every floating-point operation produces a well-defined result and will not by default throw a machine interrupt or trap.

http://en.wikipedia.org/wiki/Floating_point_arithmetic#IEEE_754_design_rationale

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Dakuan schrieb:

Das mit den Limits ausgeben lasen habe ich noch nicht verstanden. Aber es ist ja auch schon spät, vielleicht erkenne ich das morgen früh.

Hast Du Dir die Beispiele unten nicht angeguckt? Ist doch trivial:

1
std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << '\n';

Ok, für double war keines angegeben, aber den Template-Parameter austauschen ist ja nun nicht schwer ☺

@rklm: Wenn es doch um C++ geht, wieso verlinkst Du die C-Variante?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Lysander schrieb:

@rklm: Wenn es doch um C++ geht, wieso verlinkst Du die C-Variante?

Weil double und Co. sowieso gleich sind und ich auf die Schnelle nicht den passenden Link gefunden habe.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

rklm schrieb:

user unknown schrieb:

Keba schrieb:

Solche Überläufe werfen keinen Fehler. Dein Programm rechnet dann eben mit einer entsprechenden Zahl weiter.

Ja - das Motto dahinter lautet: Lieber schnell als richtig. Ist bei Java auch nicht besser.

Das liegt daran, dass beide - wie alle ernst zunehmenden Sprachen - den Standard IEEE 754 implementieren. Siehe auch:

Eine seltsame Darstellung von Ursache und Wirkung ("liegt daran") - als ob nicht der Standard von Menschen gemacht wäre und die Entscheidung sich an diesen zu halten desgleichen.

Der Einschub wie alle ernst zunehmenden Sprachen ist da nur noch zynisch, in dem er allen Sprachen, die die Korrektheit der Geschwindigkeit vorziehen als nicht ernstzunehmen diffamiert.

The special values such as infinity and NaN ensure that the floating-point arithmetic is algebraically completed, such that every floating-point operation produces a well-defined result and will not by default throw a machine interrupt or trap.

Es ging um stillschweigenden Überlauf, nicht um NaN oder Inf, oder?

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6488

Wohnort: Hamburg

Ok, für double war keines angegeben, aber den Template-Parameter austauschen ist ja nun nicht schwer

Das hatte ich gestern nicht realisiert. Den kleinen Denkanstoß brauchte ich noch. Das Ergebnis ist:

Maximum value for double: 1.79769e+308

Das ist ja noch einiges von dem weg, was mir ausgedruckt wird. Da schwanken die Exponenten zwischen 10 und 13. Vielleicht muss ich die Erklärung doch woanders suchen oder mir eine andere Strategie einfallen lassen.

Es ging um stillschweigenden Überlauf, nicht um NaN oder Inf, oder?

Ja, es kommen nur Addition und Subtraktion vor.

UbuntuInAustria

Anmeldungsdatum:
9. Juni 2010

Beiträge: 537

Wohnort: /home

Hallo,

also ich habe mich auch schon mit CIC-Filtern beschäftigt. Ich frage mich nur, woher du das mit dem Überlauf nimmst?

Die Grafik sieht gut aus, außer eben der dritte und letzte "Hügel" in der Grafik. Sieht für mich aus, also "schwingt" da irgendetwas, was ja signaltheoretisch bei CIC Filter (Sonderfall von FIR Filtern) nicht vorkommen sollte. Hast du vl. so einen kleinen Fehler im Code? Das soll jetzt kein Vorwurf sein, ich programmiere auch viel und weiß, wie schnell man eine Kleinigkeit übersieht.

Ich kann es jetzt nicht begründen, aber ich habe das gefunden: http://www.dsprelated.com/showmessage/67607/1.php → Dort heißt es, CIC geht nur mit Fixkomma ohne Saturation, aber nicht mit Gleitkomma.

// EDIT: Vermutlich basiert der CIC-Filter auf gegenseitiger Auslöschung bei der Berechnung und das klappt mit Gleitkomma nun einmal nicht, da eben minimal Differenzen bleiben, man kann Gleitkomma ja auch nicht sinnvoll mit == vergleichen, sondern nimmt immer ein zulässiges Delta.

Sieht übrigens sehr interessant aus dein Tool 👍

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6488

Wohnort: Hamburg

Ich frage mich nur, woher du das mit dem Überlauf nimmst?

Na ja, wenn man "Integrator" sagt, klingt ja im Hintergrund immer schon "Überlauf" mit. Aber sitdem ich gestern gesehen habe dass es da noch etwas Sicherheitsabstand gibt, bin ich zu einer andere Ansicht gekommen.

Hast du vl. so einen kleinen Fehler im Code?

Das will und kann ich nicht ausschließen. Deshalb mache ich das Ganze ja. Denn es ist bestimmt schwieriger so etwas in einer fertigen Anwendung zu debuggen. Und die optische Darstellung hat tatsächlich Ähnlichkeit mit Schwingungen. Ich habe allerdings auch deutlich schlimmere Bilder erzeugen können, die mehr wie Treppenstufen aussehen.

An Schwingungen wollte ich aber nicht glauben, weil hier steht:

The normally risky situation of having a filter pole directly on the unit circle need not trouble us here because there is no coefficient quantization error in our Hcic(z) transfer function.

Allerdings wird da auch die Festkomma Arithmetik erwähnt.

Dort heißt es, CIC geht nur mit Fixkomma ohne Saturation, aber nicht mit Gleitkomma.

Nachdem ich jetzt länger darüber nachgedacht habe, könnte ich mir schon vorstellen, das es hier tatsächlich ein Genauigkeitsproblem gibt. Zahlen in Fließkomma Darstellung kann man nur addieren, wenn die Exponenten gleich sind. Diese müssen also vorher angeglichen werden. Da könnte ich mir vorstellen, dass es dabei durch Schiebeoperationen in der Mantisse zum Verlust signifikanter Stellen kommt, wenn der Unterschied zu groß ist.

Eine Umstellung auf Festkomma Arithmetik konnte ich noch nicht vornehmen, da ich keine Ahnung habe wie viele Stellen vor und hinter dem Komma benötigt werden. Ich habe nur gelesen, das mit jeder Ordnungsstufe die Anzahl der benötigten Bits steigt.

Sieht übrigens sehr interessant aus dein Tool

Das jetzt schon als Tool zu bezeichnen ist wohl etwas hoch gegriffen. Da fehlt noch zu viel, z.B. Import der Koeffizienten aus anderen Quellen oder manuelles editieren/eingeben. Ein Impulsgenerator oder Import von WAV Dateien wären auch noch interessant. Aber das kostet alles Zeit...

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Dakuan schrieb:

Nachdem ich jetzt länger darüber nachgedacht habe, könnte ich mir schon vorstellen, das es hier tatsächlich ein Genauigkeitsproblem gibt. Zahlen in Fließkomma Darstellung kann man nur addieren, wenn die Exponenten gleich sind. Diese müssen also vorher angeglichen werden. Da könnte ich mir vorstellen, dass es dabei durch Schiebeoperationen in der Mantisse zum Verlust signifikanter Stellen kommt, wenn der Unterschied zu groß ist.

Ja, die Numerik kann trickreich sein. ☺

Eine Umstellung auf Festkomma Arithmetik konnte ich noch nicht vornehmen, da ich keine Ahnung habe wie viele Stellen vor und hinter dem Komma benötigt werden. Ich habe nur gelesen, das mit jeder Ordnungsstufe die Anzahl der benötigten Bits steigt.

Ich glaube nicht, dass das eine Lösung ist, wenn die Werte so stark differieren, denn Ganzzahlen haben auch nur eine beschränkte Anzahl Bits - oft sogar weniger als Fließkommazahlen. Ggf. brauchst Du ein Paket für Arithmetik mit beliebiger Präzision (vielleicht von boost).

Ciao

robert

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6488

Wohnort: Hamburg

Ich glaube nicht, dass das eine Lösung ist, wenn die Werte so stark differieren, denn Ganzzahlen haben auch nur eine beschränkte Anzahl Bits...

Ich glaube doch. UbuntuInAustria hat zitiert:

CIC geht nur mit Fixkomma ohne Saturation

Ich habe jetzt nochmal nachgesehen was Saturation in diesem Zusammenhang bedeutet und es sieht so aus, das der Trick darin besteht den Überlauf einfach im negativen Teil wieder "einzublenden". Habe dazu gerade das hier gefunden.

Um das auprobieren zu können muss ich mir aber wohl noch einen sinnvollen "Umrechnungsfaktor" einfallen lassen, denn meine Eingabewerte liegen im Bereich 0.0 bis 1.0 und so will ich auch das Ergebnis haben.

Antworten |