PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 64 Bit sind nicht genug!


Plutos
2007-07-24, 20:25:05
Heyhey,

Visual Basic .Net bietet mir als genauesten Datentyp "double" an, mit 64bit. Das ist für die gestellten Anforderungen jedoch nicht präzise genug. Wie komme ich an einen Datentyp, der mehr Nachkommastellen speichern kann? Funktioniert das überhaupt?

Und wie hängen eigentlich die bit des Datentyps mit den bit der CPU zusammen bzgl. Kompatibilität und Ausführungsgeschwindigkeit? Laufen Berechnungen mit 64bit-Datentypen auf 64bit-CPUs schneller als auf 32bit-CPUs?

RMC
2007-07-24, 21:06:22
unsigned long double? Hat glaub ich 69 Nachkommastellen soweit ich das in Erinnerung hab - ist dann aber nur im Bereich größer 0...nicht genug? -> Arrays.

Edit: Crap..vergiss es, das waren 69 Stellen, nicht 69 Nachkommastellen.. :(

Trap
2007-07-24, 21:19:38
string kann genügend Nachkommastellen speichern. Mit rechnen willst du ja nicht, oder?

Coda
2007-07-24, 21:23:18
Visual Basic .Net bietet mir als genauesten Datentyp "double" an, mit 64bit. Das ist für die gestellten Anforderungen jedoch nicht präzise genug. Wie komme ich an einen Datentyp, der mehr Nachkommastellen speichern kann? Funktioniert das überhaupt?
Erstmal sollten wir wissen was du rechnen willst wofür man mehr als 64-Bit-Präzission braucht. Bei .NET isses soweit ich weiß schwierig. Unter Java gibt's ne Bignum-Klasse (die aber arschlahm ist).

Für C/C++ würde es GNU MP geben, das mit beliebiger Präzision rechnen kann. http://gmplib.org/

Und wie hängen eigentlich die bit des Datentyps mit den bit der CPU zusammen bzgl. Kompatibilität und Ausführungsgeschwindigkeit? Laufen Berechnungen mit 64bit-Datentypen auf 64bit-CPUs schneller als auf 32bit-CPUs?
Integer: Ja. Float: Nein.

unsigned long double?
Eeeerm. Ein Float-Datentyp kann nicht unsigned sein.

string kann genügend Nachkommastellen speichern. Mit rechnen willst du ja nicht, oder?
Du Arsch :D

Plutos
2007-07-24, 21:36:45
string kann genügend Nachkommastellen speichern. Mit rechnen willst du ja nicht, oder?

Ertappt ;) (als Notlösung würd' ich mir aber daraus was basteln...nur ist das dem Performance-Ansatz nicht gerade zuträglich, denke ich). Was will ich rechnen? Vereinfacht gesagt, einen Ausdruck der Form a/(a+b). Dabei stoße ich auf folgendes Problem:
wenn a sehr sehr sehr klein wird, b jedoch noch viel viel viel kleiner ist (so dass ein Ergebnis knapp unter 1 (=a/a in guter Näherung) korrekt wäre), rechnet VB: a+b=0 => aus die Maus.
(Zum Verständnis: exp(-7000) liefert schon Werte, die ganz grob so bei 1x10^-250 oder 1x10^-300 liegen...und double geht "nur" bis irgendwas 1,x10^-308 :frown:).

Eine dazu äquivalente Fragestellung wäre damit: wie bringe ich VB intelligente Partialbruchzerlegung und Kürzen bei ;)?

Coda
2007-07-24, 21:39:35
Wie jetzt? a (sehr klein) + b (sehr sehr klein) = 1?

Bissel genauer. Ich vermute dass du irgendwo eine NAN oder sowas drin hast. Das könnte man auch abfangen. Kannst du den Debugger bedienen?

rotalever
2007-07-24, 21:52:15
Wie jetzt? a (sehr klein) + b (sehr sehr klein) = 1?

a = 0.0000001
b = 0.00000000000000000001
c = a+b = 0.00000010000000000001
a/c ~= 1

Was soll hier überhaupt gerechnet werden? Genau sind floats eben nie.

Coda
2007-07-24, 21:55:40
a = 0.0000001
b = 0.00000000000000000001

sollte dann aber a+b=0.0000001 geben und somit passen. Ich vermute das b zu klein ist um repräsentiert werden zu können.

rotalever
2007-07-24, 22:10:42
a = 0.0000001
b = 0.00000000000000000001

sollte dann aber a+b=0.0000001 geben und somit passen. Ich vermute das b zu klein ist um repräsentiert werden zu können.
Das dürfte aber ja beim Ausdruck a/(a+b) eigentlich gar keine Probleme bereiten :confused:
Auch wenn b zu klein wird existiert a ja noch. Also irgendwie kann ich mir das nicht so ganz vorstellen. Wird vll. a auch zu klein?

a = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000001

Oder ist da vll. was negativ?

Monger
2007-07-24, 22:15:33
Ist das überhaupt ein Problem, was durch höhere Genauigkeit zu erschlagen ist?

Gleitkommazahlen sind imho wahrscheinlich nicht was du brauchst. Dadurch dass die "Auflösung" bei Gleitkommazahlen über die gesamte Breite hinweg variiert, kommen bei Multiplikation und Division von sehr unterschiedlichen Werten oft komische Ergebnisse raus.

Ich vermute, du brauchst etwas, was wirklich Formeln auswerten und interpretieren, und nicht etwa stur ausrechnen kann. Leider ist das alles andere als trivial...

Plutos
2007-07-24, 22:21:39
So, darum geht's. Ae und Ar sind Attraktiven zweier Strategien, We und Wr die Gewichtungen dieser Strategien, es gilt immer: Wr+We=1 (sieht man ja ;)).
t ist ein diskreter Zeitindex. Was passiert nun für...

[CODE]t=113: Ae=-400; Ar=-6300; We=1; Wr=0
t=114: Ae=-700; Ar=-7400; We=1; Wr=0
t=115: Ae=-1028; Ar=-7453; We=-1.#IND; Wr=-1.#IND

h ist übrigens gleich 1, können wir also erstmal weglassen.
Ab diesem Punkt kommt also mit dem Ausdruck exp(-7453) nicht mehr klar (oder so ;)). Und dann geht halt nix mehr :frown:.

Bzgl. "mit Debugger umgehen"...naja, es geht so; ich beberrsche halt VB nur als Mittel zum Zweck, learning by doing bzw. quick'n'dirty und so ;). Darauf, dass nicht jede beliebige Zahl auch als Gleitkommazahl dargestellt werden kann (oder so ähnlich), bin ich auch schon gestoßen. Bringt das jetzt was? Grundsätzlich wäre es wahrscheinlich auch möglich, die Ausdrücke für We und Wr entsprechend so zu transformieren, dass man das Problem quasi umschifft. Das wäre aber bzgl. der einfachen Erweiterbarkeit wieder problematisch, da man dann immer auf solche Umleitungen Rücksicht nehmen müsste.

rotalever
2007-07-24, 22:46:10
[CODE]
Ab diesem Punkt kommt also mit dem Ausdruck exp(-7453) nicht mehr klar (oder so ;)).

exp(-1028) sollte ja eigentlich auch ~0 sein. Dann ist es klar, warum er durch 0 teilt. Man ja exp(-7453) vorher ausrechnen und überprüfen ob es zu "nah" an 0.0 heran kommt. Dann nimmt man das erste Ergebnis immer als 1 an und das zweite eben als 0. Damit könnte man diesen "Sonderfall" eben auschließen. Genauer wird es dadurch natürlich nicht.

Neomi
2007-07-24, 22:50:00
Das Problem läßt sich leicht mathematisch umgehen.

exp(a) / (exp(a) + exp(b))
= (exp(a) * exp(n)) / ((exp(a) + exp(b)) * exp(n))
= (exp(a) * exp(n)) / (exp(a) * exp(n) + exp(b) * exp(n))
= exp(a + n) / (exp(a + n) + exp(b + n))

Wenn du n als -a oder -b festlegst, dann hast du diese beiden Möglichkeiten:

exp(a) / (exp(a) + exp(b)) = 1 / (1 + exp(b - a))

bzw.

exp(a) / (exp(a) + exp(b)) = exp(a - b) / (exp(a - b) + 1)

Für die andere Hälfte gilt genau das gleiche bzw. einfach "Wr = 1 - We".

Ab diesem Punkt kommt also mit dem Ausdruck exp(-7453) nicht mehr klar (oder so ;)). Und dann geht halt nix mehr :frown:.

Damit kommt er prima klar, es kommt halt 0 als Ergebnis raus. Das Problem ist, daß exp(-1028) auch schon 0 ergibt, exp(-1028) + exp(-7453) immer noch 0 ist und daher eine Division durch 0 ausgeführt wird. Mit der mathematischen Umformung wie beschrieben kann das nicht mehr vorkommen.

Plutos
2007-07-24, 23:26:28
Das Problem läßt sich leicht mathematisch umgehen.

exp(a) / (exp(a) + exp(b))
= (exp(a) * exp(n)) / ((exp(a) + exp(b)) * exp(n))
= (exp(a) * exp(n)) / (exp(a) * exp(n) + exp(b) * exp(n))
= exp(a + n) / (exp(a + n) + exp(b + n))

Wenn du n als -a oder -b festlegst, dann hast du diese beiden Möglichkeiten:

exp(a) / (exp(a) + exp(b)) = 1 / (1 + exp(b - a))

bzw.

exp(a) / (exp(a) + exp(b)) = exp(a - b) / (exp(a - b) + 1)

Für die andere Hälfte gilt genau das gleiche bzw. einfach "Wr = 1 - We".



Damit kommt er prima klar, es kommt halt 0 als Ergebnis raus. Das Problem ist, daß exp(-1028) auch schon 0 ergibt, exp(-1028) + exp(-7453) immer noch 0 ist und daher eine Division durch 0 ausgeführt wird. Mit der mathematischen Umformung wie beschrieben kann das nicht mehr vorkommen.

Genial! Auf die Umformung hätt' ich selber auch kommen können, aber hey, super Sache. Leider kann ich das vorläufig nur als Workaround verwenden, da die Leute, die nachher derartige Gleichungen eingeben werden, diese Umformungen nicht zwangsläufig korrekt implentieren würden - aber hey, da ich jetzt echt dringend schnell gute Ergebnisse brauche, ist deine Methode absolut perfekt (wenn auch u.U. noch nicht der Weisheit letzter Schluss, dass Grundproblem, dass derart kleine Zahlen zu 0 gerundet werden, bleibt vorerst; allerdings ist das jetzt schon drastisch entschärft).

Danke danke danke, du hast meinen Abend gerettet :smile:.

Edit: damit du siehst, was du geschaffen hast ;):
http://img464.imageshack.us/img464/7179/capturenq5.png (http://imageshack.us)

Neomi
2007-07-24, 23:42:56
Danke danke danke, du hast meinen Abend gerettet :smile:.

Freut mich, daß ich helfen konnte. :)

Eine Sache noch, da ich das gerade ausprobiert habe: 1 / (1 + exp(b - a)) ist immer besser als exp(a - b) / (exp(a - b) + 1), da a deutlich von b abweichen kann. 1 / +Inf ergibt 0, also ein passendes Ergebnis, während +Inf / +Inf unschön enden kann.