Seite 1 von 2

BigDecimal - Include

Verfasst: 11.05.2010 16:32
von CSHW89
BigDecimal - Include
Unicode, 32-Bit

So, habs ja Stargate versprochen, hier nun meine Include zum Thema unendlich große und genaue Decimalzahlen.
(Vergleich: http://www.purebasic.fr/german/viewtopi ... =8&t=19344)

Ein paar Anmerkungen dazu:
- Hab mich entschieden, keinen Speicher zu allocieren. Der Benutzer muss die Adresse als Parameter angeben, wo das Ergebnis gespeichert werden soll. Das sollte eine Variable mit dem Typ 'BigDecimal' sein (siehe auch Beispiel unten).
- Die Adresse des Ergebnisses kann die gleiche sein, wie einer der anderen Parameter.
- Der Parameter 'digits' kann in den meisten Fällen angegeben werden. Er limitiert die Berechungszeit und den gebrauchten Speicher. Das Ergebnis ist dann aber nicht mehr genau. Bei den Funktionen 'exp' und 'log' muss 'digits' angegeben werden.
- Falls 'digits' angegeben wird, wird gerunden. Wie gerundet wird, kann man selbst entscheiden (BDRoundMode).

So hier jetzt noch ein Beispiel:

Code: Alles auswählen

Define.BigDecimal bda, bdb, result

BDFromQuad(2947, bda)
BDFromString("0.000000000000000001", bdb)
BDAdd(bda, bdb, result)
Debug BDStr(result)
Debug BDStr(result, 10)

BDFromString("10", bda)
BDFromString("3", bdb)
BDDiv(bda, bdb, result, #Null, 200)
Debug BDStr(result)

BDFromString("1", bda)
BDExp(bda, result, 200)
Debug BDStr(result)

BDFromString("150", bda)
BDLog(bda, result, 200)
Debug BDStr(result)

BDFromDouble(-Infinity(), bda)
BDExp(bda, result, 20)
Debug BDStr(result)

BDFromString("12.74", bda)
BDFromString("12.75", bdb)
Debug BDStr(bda, 1)
Debug BDStr(bdb, 1)

BDRoundMode(#BDRoundHalfUp)

BDFromString("12.74", bda)
BDFromString("12.75", bdb)
Debug BDStr(bda, 1)
Debug BDStr(bdb, 1)
Und hier der Link:
http://cshw89.mevedia.de/BigDecimal.pb

Freu mich auf Kritik, Anregungen ect., blablub....

mfg kevin

Re: BigDecimal - Include

Verfasst: 11.05.2010 18:31
von STARGÅTE
Tachchen,

bin gerade dabei alles auszutesten
Hier mal n kleiner Fehler:
Bei BDFromDouble() verwendest du IsInfinity(), dass ist jedoch nur für Floats !!! damit kann man keine hohen Doubles übergeben

Ich finde aber interessant das deine proceduren schneller sind, obwohl die eigentlich eine "sinnlose" aktion machst:
CopyArray(help(), *result\man())

Das frist doch Zeit .. Wieso speicherst du die errechneten Werte nciht gleich in der neuen Zahl ab ?
Denn auch wenn das ergebnis ich die gleiche Zahl kommt, wie eine die übergeben würde, wird beim errechnen ja est das Feld ausgelesen udn dann erneuert, sollte also kein Fehler verursachen ...


EDIT:

Ein großen Problem gibs jedoch bei erreichen einer Potenz:

Code: Alles auswählen

Procedure BDPow(*a.BigDecimal, *b.BigDecimal, *c.BigDecimal, d)
  BDLog(*a, *c, d)
  BDMul(*b, *c, *c, d)
  BDExp(*c, *c, d)
EndProcedure
Wenn man da nur 10^10 berechnen lassen will, wirds entweder ungenau, oder dauert lange.
Da solltest du unbedingt noch n alternative einauen für Ganzzahlige Exponenten ...

Auch zum wurzelziehen, wäre das heron-Verfahren schneller.
Die EXP-Log variante wird nur schneller wenn der WurzelExponent groß ist.

Re: BigDecimal - Include

Verfasst: 11.05.2010 19:04
von CSHW89
STARGÅTE hat geschrieben:Hier mal n kleiner Fehler:
Bei BDFromDouble() verwendest du IsInfinity(), dass ist jedoch nur für Floats !!! damit kann man keine hohen Doubles übergeben
ist gefixed
STARGÅTE hat geschrieben:Ich finde aber interessant das deine proceduren schneller sind, obwohl die eigentlich eine "sinnlose" aktion machst:
CopyArray(help(), *result\man())

Das frist doch Zeit .. Wieso speicherst du die errechneten Werte nciht gleich in der neuen Zahl ab ?
Denn auch wenn das ergebnis ich die gleiche Zahl kommt, wie eine die übergeben würde, wird beim errechnen ja est das Feld ausgelesen udn dann erneuert, sollte also kein Fehler verursachen ...
tja, doch. sagen wir mal bei der multiplikation. die hab ich mit der schrichtichen multiplikation, wie in der schule, realisiert. dort braucht man auch zum schluss (also ganz vorne) noch beide operanten komplett beim rechnen.
STARGÅTE hat geschrieben:EDIT:
Ein großen Problem gibs jedoch bei erreichen einer Potenz:
Code:
Procedure BDPow(*a.BigDecimal, *b.BigDecimal, *c.BigDecimal, d)
BDLog(*a, *c, d)
BDMul(*b, *c, *c, d)
BDExp(*c, *c, d)
EndProcedure

Wenn man da nur 10^10 berechnen lassen will, wirds entweder ungenau, oder dauert lange.
Da solltest du unbedingt noch n alternative einauen für Ganzzahlige Exponenten ...

Auch zum wurzelziehen, wäre das heron-Verfahren schneller.
Die EXP-Log variante wird nur schneller wenn der WurzelExponent groß ist.
habs auch schon gemerkt, wollte eigentlich 'Pow' auch bereitstellen. hab aber gemerkt, dass das nicht so ganz das wahre ist, werd mich die nächsten tage damit beschäftigen.
STARGÅTE hat geschrieben:Ich finde aber interessant das deine proceduren schneller sind
:mrgreen: :mrgreen:

lg kevin

Re: BigDecimal - Include

Verfasst: 11.05.2010 19:21
von STARGÅTE
Aber von der Speed her, werden wir wohl immer Schlusslicht bleiben ...

EXP(1000) mit 100 Nachkommastellen, da "zuckt" Mathematicer nicht mal.
Bei mir (mit errechnetenm e und Power() ) dauert es 4 Sekunden
Und bei dir dauert das 8 Sekunden mit Exp()
Immerhin liefert es bei uns beiden die gewünschte genauigkeit ^^ :allright:


Ich habe mich übrignes dazu entschlossen, weiter auf dem "Schulweg" zu fahren, also so wenig näherungsverfahren, wie es geht.
Das macht zwar einiges langsammer, dafür habe ich fast überall unendliche genauigkeit!
Somit soltle gesichert sein, das unsere Includes sich unterscheiden.


Trotzdem würde ich gerne auch von den Memorys wegkommen und die Variable-Variante "kopieren" (hoffe du hast nix dagegen ^^), gleich verbunden mit dem bei mir angesprochenen Interface ...


Zur Multiplikation, jo da habe ich auch n Hilfe-Array, ich meinte ja nur bei Addition ...

Re: BigDecimal - Include

Verfasst: 11.05.2010 19:40
von CSHW89
STARGÅTE hat geschrieben:Ich habe mich übrignes dazu entschlossen, weiter auf dem "Schulweg" zu fahren, also so wenig näherungsverfahren, wie es geht.
Das macht zwar einiges langsammer, dafür habe ich fast überall unendliche genauigkeit!
Somit soltle gesichert sein, das unsere Includes sich unterscheiden.
also ehrlich gesagt, weiß ich nicht so ganz, was du damit meinst. wenn du damit auf die 'div'-methode ansprichst, ich hatte ja erklärt, wie ich sie umgesetzt hab. ich sagte ja, ich berechne nährungsweise das ergebnis, damits schneller geht, es wird aber dann korrigiert, somit hat es die gewünschte genauigkeit, und wenn man so will, auch eine unendliche genauigkeit. wenn dies nicht so wäre, würde 'exp' auch nicht das gewünschte ergebnis liefern. das tuts aber, wenn man für 'digits' 1000 übergibt, sind auch alle 1000 (oder sagen wir 998) ziffern GENAU richtig.
STARGÅTE hat geschrieben:Trotzdem würde ich gerne auch von den Memorys wegkommen und die Variable-Variante "kopieren" (hoffe du hast nix dagegen ^^), gleich verbunden mit dem bei mir angesprochenen Interface ...
klar, hab ich nix gegen, kannste ruhig machen. ich hatte ja auch nur die idee, weil ja arrays in structuren jetzt möglich sind. sonst wäre das ja so nicht machbar.

lg kevin

Re: BigDecimal - Include

Verfasst: 14.05.2010 20:15
von CSHW89
So hab eine kleine Änderung bei 'Log' vorgenommen. Die Funktion ist jetzt ca. 2000% schneller (ich glaub sogar noch schneller) als die alte Version. Downloadlink am Anfang.

lg kevin

Re: BigDecimal - Include

Verfasst: 20.06.2010 20:55
von Helle
@CSHW89: Schau mal Deine Subtraktion an:

Code: Alles auswählen

  66666666666665487986458484884684145737458469659244125252362634719113453253487793
-                                             734769847345737373711118058795087095
---------------------------------------------------------------------------------
  66666665666665486986458483884684144737458468924474277906625260007995394458400698  Dein Ergebnis
  66666666666665487986458484884684145737458468924474277906625261007995394458400698  Mein Ergebnis
Da meine heißgeliebten BCD´s in meinem Calculator von einem 64-Bit-OS nicht mehr unterstützt werden, habe ich mal ein wenig mit SSE (Add, Sub) gespielt und Deinen Code zum Ergebnis-Vergleich benutzt.

Gruß
Helle

Re: BigDecimal - Include

Verfasst: 20.06.2010 21:10
von STARGÅTE
Das sieht sehr nach einem Übertragsfehler aus.

Und hier ist auch schon der Fehler gefunden:
Codeausschnitt:

Code: Alles auswählen

  ub = 0
  While (i < sman)
    ; [...] 
    If (long < 0)
      ; Erste Zahl ist kleiner als zweite -> Übertrag
      long + #BDMaxInLong
      ub = 1
    EndIf
    help(i-eman) = long
    i + 1
  Wend
ub ist zum anfang 0, wenns dann aber mal 1 wird, bleibt es für immer 1 .
Dort fehlt also ein Else : ub = 0

@Helle: Nimm lieber mein Include :lol: , ne quatsch war n Witz :wink:

Re: BigDecimal - Include

Verfasst: 20.06.2010 21:12
von CSHW89
Ja habs grad auch gefunden, wollte es nochmal testen
lg kevin

Re: BigDecimal - Include

Verfasst: 20.06.2010 21:21
von CSHW89
Mal ne frage, kann das jemand bestätigen: ich hab grad ne komische fehlermeldung mit asm-irgendwas-blabla.

edit: liegt übrigens an 'BDExp'. hat aber vor 4.50 final noch funktioniert.
edit2: ok das liegt i-wie an den 'Protected' aufrufen in den proceduren 'BDExp' und 'BDLog'