float vs. double
-
Sone schrieb:
Ich hätte jetzt double genommen, aber SFML rechnet alles in float.
Hat gute Gründe. Ogre nimmt auch
float
für FließkommazahlenNämlich?
-
out schrieb:
Sone schrieb:
Ich hätte jetzt double genommen, aber SFML rechnet alles in float.
Hat gute Gründe. Ogre nimmt auch
float
für FließkommazahlenNämlich?
Beispielsweise GPUs funktionieren mit single-precision teilweise deutlich schneller.
Wikipedia:Using floating-point variables and mathematical functions (sin(), cos(), atan2(), log(), exp(), sqrt() are the most popular ones) of double precision as opposed to single precision comes at execution cost**: the operations with double precision are usually slower**. On average, on a PC of year 2012 build, calculations with double precision are 1.1–1.6 times slower than with single precision.
One area of computing where this is a particular issue is for parallel code running on GPUs. For example when using NVIDIA's CUDA platform, calculations with double precision are 3 to 8 times slower than float.
Siehe auch hier: http://stackoverflow.com/questions/2079906/float-vs-double-on-graphics-hardware
Du kannst bei Grafikoptionen auch manchmal zwischen schnelleren oder genaueren Fließkommazahlberechnungen wählen (fastest vs. consistent).
Der Support für double als Fließkommazahl ist aber eigentlich eine Ausnahme, sie he auch den Stackoverflow-Link.
-
out schrieb:
Sone schrieb:
Ich hätte jetzt double genommen, aber SFML rechnet alles in float.
Hat gute Gründe. Ogre nimmt auch
float
für FließkommazahlenNämlich?
Performance. Google mal nach "Vector Instructions". Ein Beispiel fuer Vector Instructions waere Intel SSE (insbesondere SSE3).
-
Sone schrieb:
Gerade in Schleifen sollte man mit Fließkommazahlen aufpassen, da dort schon kleine Abweichungen (wie glühbirne bereits erwähnte) akkumuliert werden und sich anstauen.
Nein, Schleifen sind nicht das Problem. Sone, ich habe jetzt nicht das Gefühl, das du ein Experte für Fließkommazahlen bist
.
Also der Onkel otze sacht mal, wie das läuft:
Also das einzige, was man über floats wirklich wissen muss ist, das sie nicht jede Zahl darstellen können. Nach einer bestimmten Menge dezimalstellen ist schluss, und je größere Zahln du darstellen willst, desto weniger gibt es. Also ist es ziemlich blöd, irgendwie zu testen ob zwei fließkommazahlen glich sind, si sind es nämlich nicht. Unabhängig davon wird die Situation nur Marginal besser, wnn du double verwendest. die Lücken werden kleiner, aber das wars.Für Spiele ist es eigentlich schnurz, wie du Dinge berechnest, der berechnete Fehler ist fast nie Ausschlaggebend. Darauf reiten Physiker rum oder Leute die in 2500 Dimensionen rechnen und plötzlich das Gefühl haben, das sich die Fehler immer weiter aufschaukeln. In der Realität rennen natürlich noch Leute wie Sone mit ihrm Aluhut rum, aber die muss man ignorieren.
Ohja, und teile nicht durch 0. Aber das weißt du sicher schon
-
Nein, Schleifen sind nicht das Problem
Nein, nicht das Problem, ich bezog' mich ja auch auf Glühbirnes Beispielcode. Wieso leitest du daraus ab, dass ich Schleifen als eines der größten Probleme in dem Zusammenhang sehe?
-
otze schrieb:
In der Realität rennen natürlich noch Leute wie Sone mit ihrm Aluhut rum, aber die muss man ignorieren.
Hä, wie meinsten das?
otze schrieb:
Ohja, und teile nicht durch 0. Aber das weißt du sicher schon
Nur mal für mein Verständnis und unabhängig von algebraischen Strukturen:
Wenn ich eine Gleitkommazhal durch 0 teile, sollte doch sowas wie #inf oder #NaN rauskommen, oder?
Und das weitergesponnen, wenn man mit solchen Werten weiterrechnet, bleibt man nur im Bereich von #inf oder #Nan ?!
-
Rein technisch gesehen...
If the second operand of / or % is zero the behavior is undefined.
Allerdings
[ Note: most existing implementations of C++ ignore integer overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines, and is usually adjustable by a library function. —end note ]
-
Man unterscheided zwischen quiet und signaling NaNs. Quiet NaNs propagieren einfach durch, d.h. sobald irgendwo ein NaN reinkommt, werden alle in weiterer Folge mit dem Wert durchgeführten Berechnungen wieder ein NaN ausspucken. Wenn also irgendwo ein NaN rauskommt, dann weißt du, dass entweder irgendwo ein NaN reingegangen ist, oder in der Berechnung eines erzeugt wurde. Signaling NaNs dagegen lösen sofort eine Hardware Exception aus. #Inf selbst ist einfach nur ein bestimmmter NaN Wert. Ja nach Hardware kann es desweiteren sein, dass Rechenoperationen mit NaNs wesentlich langsamer sind als Rechenoperationen mit normalen Zahlenwerten.
Generell: double braucht doppelt so viel Speicher usw. Wenn float also ausreichend ist, dann rechne mit float, double erst, wenn nicht vermeidbar. Im Bereich Grafik wird man kaum double benötigen, ist mir eigentlich noch nie untergekommen. Und Grafikkarten mögen double überhaupt ganz und gar nicht (grottenlangsam; wenn du Pech hast wechselt der Driver z.B. bei OpenGL überhaupt in einen Softwarepfad). Jüngstes Extrembeispiel wäre da z.B. die GeForce GTX 680, wo double Arithemtik um Faktor 24 langsamer ist als float Arithmetik (rein nur die Arithmetik, die Verdoppelung des Bandbreitenbedarfs tut da dann zusätzlich nochmal ordentlich weh)...
-
Vielen Dank, das hat mir schonmal weitergeholfen.
Noch eine Frage: Ist float geeignet um die Positionen in einem begrenzten kontinuierlichen Koordinatensstem (sagen wir, von 0/0 bis 1/1, jeder Wert dazwischen ist erlaubt) zu speichern? Nach dem, was ich gelesen habe, wird die Position gegen 0/0 immer genauer und gegen den Rand hin immer ungenauer, was etwas seltsam ist.
-
tripl3 schrieb:
Vielen Dank, das hat mir schonmal weitergeholfen.
Noch eine Frage: Ist float geeignet um die Positionen in einem begrenzten kontinuierlichen Koordinatensstem (sagen wir, von 0/0 bis 1/1, jeder Wert dazwischen ist erlaubt) zu speichern? Nach dem, was ich gelesen habe, wird die Position gegen 0/0 immer genauer und gegen den Rand hin immer ungenauer, was etwas seltsam ist.
Wenn du dir dessen bewusst bist: Klar, warum nicht? Ich verstehe aber nicht, was du da dran seltsam findest. Das ist doch in der Regel genau das, was man möchte.
Falls du unbedingt gleiche Abstände zwischen Werten brauchst, dann ist float aber nicht das richtige, sondern eine Ganzzahl. Das ist dann jedoch keine gute Annäherung an das Kontinuum mehr, sondern bloß ein diskretes Gitter mit feiner Unterteilung.
-
Ich finde es komisch, weil eigentlich jeder Ort gleich sein sollte.
Aber müsste ein int (32 Bit) nicht feiner unterteilen als ein float?
-
tripl3 schrieb:
Ich finde es komisch, weil eigentlich jeder Ort gleich sein sollte.
Es ist nicht komisch, sondern eine wunderbare Eigenschaft. Wir wollen mit Floats ganz kleine als auch ganz grosse Zahlen darstellen, haben dazu aber z.B. nur 32 Bits zur Verfuegung, d.h. wir koennen nur endlich viele Werte darstellen.
Bei kleinen Werten ist uns die Genaugkeit sehr wichtig, da schon kleine Fehler grosse Auswirkungen haben koennen (0.0001 ist stark verschieden von 0.0002).
Wenn wir mit grossen Zahlen rechnen, ist die Genauigkei etwas weniger wichtig (10^9 + 0.0001 ist praktisch das gleiche wie 10^9 + 0.0002). Aber wir koennen die grossen Zahlen darstellen und mit ihnen rechnen.
Deswegen macht es Sinn, dass je nach groesse die Zahlen unterschiedlich genau dargestellt werden. Die schoene Eigenschaft ist sogar, dass die Genauigkeit mit jeder Zweierpotenz abnimmt
-
Es ist nicht komisch, weil die Genauigkeit am Ende der zahl abnimmt.
Die ersten 7 Stellen sind genau (laut Spezifikation), hast du eine Zahl die schon 4 Stellen vor dem Komma hat, dann sind die Nachkommastellen nicht mehr so genau wie bei einer Zahl, die nur 1 Vorkommastelle hat.0.1234567 vs. 12345.67xxxxx
-
tripl3 schrieb:
Ich finde es komisch, weil eigentlich jeder Ort gleich sein sollte.
Wieso? Ist es nicht interessanter zu wissen, ob ein Wert 0.000000000000000 oder 0.000000000000001 oder 0.000000000000002 ist, als zu wissen, ob ein Wert 99999999.000000000000000 oder 99999999.000000000000001 oder 99999999.000000000000002 ist?
Aber müsste ein int (32 Bit) nicht feiner unterteilen als ein float?
Kommt drauf an, in welchem Bereich
. Der float kann nahe 0 fast beliebig fein unterteilen. Dafür aber insgesamt nur mit 23 Bit Genauigkeit.
-
Das entspricht doch auch dem intuitivem Umgang mit Zahlen unterschiedlicher Größenordnung. "In etwa hundert" ist genauer als "In etwa zwanzig Millionen".
-
SeppJ schrieb:
tripl3 schrieb:
Ich finde es komisch, weil eigentlich jeder Ort gleich sein sollte.
Wieso? Ist es nicht interessanter zu wissen, ob ein Wert 0.000000000000000 oder 0.000000000000001 oder 0.000000000000002 ist, als zu wissen, ob ein Wert 99999999.000000000000000 oder 99999999.000000000000001 oder 99999999.000000000000002 ist?
In einer Karte nicht.
-
tripl3 schrieb:
SeppJ schrieb:
tripl3 schrieb:
Ich finde es komisch, weil eigentlich jeder Ort gleich sein sollte.
Wieso? Ist es nicht interessanter zu wissen, ob ein Wert 0.000000000000000 oder 0.000000000000001 oder 0.000000000000002 ist, als zu wissen, ob ein Wert 99999999.000000000000000 oder 99999999.000000000000001 oder 99999999.000000000000002 ist?
In einer Karte nicht.
Wieso?
*Edit
Hat sich erledigt, durch den Beitrag von SeppJ weiss ich jetzt worauf du hinaus willst
-
tripl3 schrieb:
SeppJ schrieb:
tripl3 schrieb:
Ich finde es komisch, weil eigentlich jeder Ort gleich sein sollte.
Wieso? Ist es nicht interessanter zu wissen, ob ein Wert 0.000000000000000 oder 0.000000000000001 oder 0.000000000000002 ist, als zu wissen, ob ein Wert 99999999.000000000000000 oder 99999999.000000000000001 oder 99999999.000000000000002 ist?
In einer Karte nicht.
Ja. Da sind tatsächlich Ganzzahlen besser, da es sich effektiv eher um ein Gitter als um ein Kontinuum handelt. Dadurch wird die Haupteigenschaft der Fließkommazahlen, auch 10^100 oder 10^-100 problemlos darstellen zu können, kaum genutzt.
Alternativ kann man natürlich auch mit x-99999999 rechnen, nachdem man festgestellt hat, dass man sich in diesem Sektor befindet.