![]() |
Spezielle Festkommazahl?
Wäre es möglich Delphi ganz spezielle Festkomma-Datentypen beizubringen?
Ich dachte so an 1/2(Vorzeichen) Bit(s) vor dem Komma und 15/14 Bits danach. Also Wertebereich von 0 bis 1 bzw. von -1 bis +1 bei recht hoher Genauigkeit bei niedrigem Speicherbedarf. Festkomma wegen der schnelleren Verarbeitung. (Und ich habe nicht vor das ganze Prog in asm zu schreiben :D) |
Re: Spezielle Festkommazahl?
Du müsstest dir halt einen eigenen schreiben. Ab Delphi 2006 kannst du dafür auch Klassenoperatoren verwenden. Im Prinzip musst du "nur" die Funktionsweise der FPU nachahmen.
|
Re: Spezielle Festkommazahl?
Hm ok, und wie schreib ich mir den?
Ich hab Delphi 2005. Und ich müsste nur die ALU nachahmen, Festkommazahlen "sind" doch Integers. |
Re: Spezielle Festkommazahl?
Aargh, Festkommazahl... Ich hab nur das F und das Komma gelesen... ;)
Dann wird das ganze ein bissel einfacher. Du bekommst aber ein Problem, wenn du deine Zahl mit einem Integer/Cardinal oder einer Gleitkommazahl multiplizieren willst. Im Prinzip kannst du für deine Zahl auch einfach einen SmallInt nehmen und dann nur die Rechenoperationen und Ausgabeprozeduren anders implementieren. |
Re: Spezielle Festkommazahl?
Gleitkommas sollte es eigentlich nicht geben, Integers schon eher.
Wenn ich nen SmallInt nehm, wie siehts dann aus wenn ich z.B. 1x1 hab? Da steht ja dann im SmallInt 32768 x 32768. Kommt da dann wieder 32768 raus? Wohl nicht, der Windows-Rechner sagt 0. Drum müsste man da nen neuen Datentyp einführen denk ich mir. Sonst muss ich ja solche Sachen wie Plus und Minus neu schreiben und zwar als Funktionen. Oder kann man Operatoren definieren? Zur Ausgabe muss das dann als Genzzahl in ein/zwei Byte(s) gemappt werden. |
Re: Spezielle Festkommazahl?
Nein, das sagte ich bereits. Du musst die Rechenfunktionen anders implementieren.
Am einfachsten ginge das so:
Delphi-Quellcode:
function FixedMul(a, b: SmallInt): SmallInt;
var aex, bex: Extended; begin aex:=1/a; bex:=1/b; result:=round(1/(aex*bex)); end; function FixedDiv(a, b: SmallInt): SmallInt; var aex, bex: Extended; begin aex:=1/a; bex:=1/b; result:=round(1/(aex/bex)); end; |
Re: Spezielle Festkommazahl?
Ui, da war ich wohl zu langsam mit editen :D
Ich dachte an den Datentyp weils dann viel schneller zu verarbeiten wäre. Deine Funktionen sind ja eigentlich ziemlich langsam wegen den vielen Divisionen, Programmsprüngen und Extendeds (die sind ja eigentlich auch Krücken, kein PC kann mit 10 Bytes auf einmal rechnen). Und fürs Verständnis: Wieso Kehrbrüche? |
Re: Spezielle Festkommazahl?
Îch nehme mal 7F FF soll soviel wie 1 heißen. Also ist 00 01 1/32768.
Und wenn dir das zu langsam ist, kannst du deinen Code ja auch selbst schreiben, mit Binärgefummel. Allerdings wird das garantiert nicht so schnell gehen wie mit einem nativen Datentypen. |
Re: Spezielle Festkommazahl?
Im Prinzip brauchst du keinen neuen Datentyp. Integers reichen. Allerdings musst du Schiebefaktoren mitspeichern. Also: Mit Integer rechnen und immer n Schiebefaktor mitführen. ggf. noch n shr bzw. shl einbauen und fertig. So wirds jedenfalls bei "richtiger" Festkommarechnung(z.B. aufm DSP) gemacht...
Musst nur eben die versch. Rechenarten beachten: +, - ==> Schiebefaktor ändert sich nicht *, / ==> aufpassen mfg Christian |
Re: Spezielle Festkommazahl?
@3_of_8: Wieso 7F FFh (0111 1111 1111 1111b) als "1" und nicht 80 00h (1000 0000 0000 0000b)?
Wie stellst du dann z.B. 0,5 dar? Oder einfach 1? Der Kehrbruch von 1 ist bei mir 00 001h und nicht 7F FFh :? @r2c2: Der Schiebefaktor wäre ja immer gleich also kann ich den hardcoden. Nur wenn ich das hin und her-shifte, was passiert dann mit dem Nachkommateil? Der is dann weg wenn ich nicht drauf aufpasse^^. Und wie muss ich dann mit dem rechnen, ich kann mir das nicht so ganz vorstellen. Ich dachte halt Festkomma weils schneller zu behandeln ist (Integer) und es keinen 2-Byte-Gleitkommatyp gibt (Speicherbedarf). Aber ich hab grad festgestellt dass sich selbst mit Single (4 Byte) der Speicherbedarf eigentlich in Grenzen hält. Ich werds dann mal mit Singles probieren, wenns nicht tut werd ich auf Festkommas zurückkommen. Singles dürften ja schneller "sein" als Extendeds, die passen ja noch nichtmal in nen 64-Bit Prozzi rein ;) Ihr dürft natürlich weiterhin gerne versuchen mir das zu erklären :D |
Re: Spezielle Festkommazahl?
Zitat:
Delphi-Quellcode:
Ich hoff ich habs noch richtig behalten aber so scheints zu stimmen. Das is IMHO richtiges Festkomma rechen. So wirds gemacht, wenn man keine FPU hat.
var
int1: Integer; // 32 Bit; passt genau in ein Register int2: Integer; erg: Integer; erg_float: Double; shift: Integer; begin // ich definier jetzt einfach mal: positiver Schiebefaktor: shr; negativer: shl shift := 0; // ganze Zahl int1 := 1024; int2 := 512; erg := int1 + int2; // ändert nix am Schiebefaktor erg := int1 - int2; // ändert nix erg := int1 * int2; // 32 Bit * 32 Bit = 64 Bit; hier müsste ggf. geschoben werden um die 64 Bit in die 32 zu kriegen. Sollte aber bei "normalen" Zahlenbereichen überflüssig sein. Delphi meckert schon bei nem Overflow... ;-) erg := int2 div int1; // erg is eigentlich 0,5. Passt aber nicht in den Integer rein. Also schieben: int2 := int2 shl 1; // int2 anpassem shift := +1; // Shiftfaktor speichern; +1, da nach rechts geschoben werden muss um das eigentliche Ergebnis zu erhalten erg := int2 div int1; // rechnen; 1024 / 1024 = 1 // nur zur Verdeutlichung, dass auch das drin is, was soll: // in Float umwandeln = zurückschieben: if shift > 0 then erg_float := erg / Power(2, shift) // "shr für Float" else erg_float := erg * Power(2, shift); // "shl für Float" ShowMessage(FloatToStr(erg_float)); // 0,5 end; Das hat aber, wie du siehst natürlich mehrere Nachteile: - ewig langwierige Rechnerei :-( - blöd, wenn man mehr als 32 Bit shiften muss... :roll: - man muss immer wissen, in welchen Größenordnungen sich die Zahlen befinden uind demnach schieben, sonst gibts Ungenauigkeiten(Hätt ich oben nicht geschoben, wär das Ergebnis 0; - wichtig is, dass alle Zahlen die selben Schiebefaktoren haben. Wenn nicht, darfst du das auch noch berücksichtigen... Ob das das ist, was du willst, weiß ich nicht. Das Ganze nur in Festkomma zu speichern und mit Gleitkomma zu rechnen macht aber IMHO keinen Sinn, da sich dadurch nicht die Vor- sondern nur die Nachteile addieren: hoher Aufwand(Festkomma) und langsam, ungenau(Gleitkomma). Generell fragt sich, ob es Sinn macht auf Float zu verzichten. Wenn man nicht dazu gezwungen ist(keine FPU), sollte man IMHO auch die Floats nutzen... Wenn es wirklich auf die Geschwindigkeit ankommt, gibts bestimmt noch andere einfacherere Optimierungsmöglichkeiten... Zitat:
mfg Christian |
Re: Spezielle Festkommazahl?
Das sieht richtig gut aus! :thumb: :thumb: :thumb:
Aber du hast mich jetzt endgültig überzeugt, Festkomma muss nicht sein, FPU kann ich voraussetzen und Single tuts leicht. Das ganze kommt hinterher eh als Ganzzahl in einzelne Bytes, ich will nur etwas genauer rechnen: 1 => 255 0,5 => 127 0 => 0 *g* Und ich will mit Kommazahlen rechnen weils einfach viel leichter wird. Wenn ich mit den Bytes rechne muss ich bei ner Multiplikation immer durch 65535 teilen, bei ner Division mit 255 malnehmen. Das mit dem Speicherplatz sind nicht 1, 2 Bytes mehr oder weniger sondern eher 1, 2 MegaBytes ;) aber das ist ja auch zu verkraften. |
Re: Spezielle Festkommazahl?
Delphi 2006 + überladene Operatoren. Natürlich nicht einmal annähernd so schnell wie die primitiven Float-Typen, aber fast genauso leicht zu benutzen ;) .
@r2c2: Ich habe von der Materie nicht viel Ahung, aber bist du mit deinem "Shift-Faktor" nicht wieder in den Bereich der Floatpoints gewandert :gruebel: ? |
Re: Spezielle Festkommazahl?
Zitat:
Vielleicht sagst du uns mal, was du genau vor hast. Wo willst du denn nun genau, schnell oder speicherschonend sein... Zitat:
Auch hier gilt wieder: Ich hab das noch nie gemacht. Nur mal gesehen. Alle Angaben sind also wie immer ohne Gewähr, nachlesen können Sie die Lottozahlen... äh... ![]() ![]() ![]() mfg Christian P.S.: Wenns dir wirklich auf die Geschwindigkeit ankommt, verabschiede dich vom Dividieren *halb im Spaß und halb im Ernst spricht* :zwinker: |
Re: Spezielle Festkommazahl?
Ich kann es mir immer noch nicht vorstellen :zwinker: . Ein Fixed-Point-Typ hat eine einmalig festgelegte Anzahl von Stellen vor dem Komma (also < 1) und von Nachkommastellen, daran wird IMO nie etwas geändert. Vor Allem: Wie willst du "den gerade betrachteten Teil der Zahlen" definieren, speichern? Am Ende läuft das auf das Speichern des Shiftfaktors=Exponenten innerhalb jeder Variable hinaus => Floatpoint.
|
Re: Spezielle Festkommazahl?
Angenommen du hast 5 Messwerte. Alle liegen in einer anderen Größenordnung. Die musst du verrechnen und am Schluss kommt wieder n Wert raus.
Mit Gleitkommas funktioniert das so: - alle Werte verrechnen - die FPU macht das schon... - Wert am Ende ausgeben Mit Festkommas geht das folgendermaßen: - Alle Werte normieren, d.h. auf einen gemeinsamen Shiftfaktor bringen(wie bei der Bruchrechnung) - Mit den Mantissen-Werten(und nur mit denen) als Ganzzahlen rechnen - Den Wert, der an Schluss wieder rauskommt muss dann wieder angepasst werden - dann erst ausgeben Angenommen du hättest keinen variablen Shiftfaktor, dann hieße das, du rechnest nur mit Integern ohne Shiftfaktor. Das geht auch. Aber nur sehr begrenzt, da du so nicht multiplizieren kannst: Wenn du z.B. ne 2 hast: 00000010 und willst die Quadrieren geht das: 00000100. Das is aber Integer. Hast du jetzt 0,5: 00000010(Dein Shiftfaktor(den hast du zwangsweise, auch, wenn du ihn nicht änderst; ohne den gibts nämlich kein Komma) wäre dann 2). Willst du jetzt quadrieren hast du ein Problem, weil du immer noch bei deinem Shiftfaktor bleiben willst: 00000100(=1). Also 0,5*0,5=1... ähm... ne nich so ganz. Du könntest natürlich sagen, "Dann teil ich eben wieder durch 2^2.", aber das is nix anderes als mein Shiftfaktor, nur mit dem Nachteil, dass du irgendwann über den rechten Rand hinausschiebst: Quadriere nochmal und du kannst einpacken: 00000001 * 00000001 = 00000001. Dann willst du noch um eins schrieben und erhälst 00000000. Nachteil: Du hast 8 Bit(oder eben so viel du hast) ungenutzt gelassen und dein Wert is im Nirwana verschwunden. Ich nehm mal an du hast keinen buddhistischen Wert. Der wird sich also nicht so sehr darüber freuen... :roll: Im Prinzip is das also nix anderes als Emulation von Float. Deshalb sollte man auch, wenn man Floats zur Verfügung hat mit Floats rechnen(Ausbahmen bestätigen die Regel)... mfg Christian |
Re: Spezielle Festkommazahl?
@Khabarakh: Wie ich bereits sagte, es gibt keine Zahlen über 1. Also reicht es doch wenn das Komma "zwischen" dem ersten und zweiten Bit sitzt.
@r2c2: Das Festkomma ist insofern genauer als Gleitkomma weil keine Bits für den Exponenten gebraucht werden ;) Ich wollte Festkomma nehmen weil
Aber mittlerweile find ich die Herausforderung nicht mehr so spannend^^ und die Floats haben doch irgendwie die größeren Vorteile. Drum hab ich ürsprünglich auch gefragt ob Delphi nen neuen Datentyp schluckt, dann könnte ich den Rest ja ganz normal programmieren ;) |
Re: Spezielle Festkommazahl?
Wie genau muss es denn sein? N Single hat im Bereich von 0..1 ne Auflösung von 1/8388608. Das ist also ungefähr 0,00000012. IMHO doch schon recht genau... :wink: Aber so wie ich das sehe, bist du je eh schon zu Float bekehrt... :mrgreen:
//Nachtrag: Zitat:
mfg Christian |
Re: Spezielle Festkommazahl?
Soo genau müssen "Zwischenergebnisse" wohl nicht sein wenns am Schluss nur ne Auflösung von 1/256 = ca. 0,0039 gibt.
Ich wollte ja erst 16 Bits nehmen, 10 würden ja schon reichen :D Und D2006 hab ich nicht, da wärs mir eh viel zu langsam^^ |
Re: Spezielle Festkommazahl?
@r2c2: Festkommatypen haben einfach einen statischen Wertebereich, daran lässt sich nix ändern. Dass 0,25² bei einem Q6.2-Typen (also mit der Auflösung 0,25) im Nirvana verschwindet, liegt in der Natur der Sache. Kann ich diese Einschränkung nicht gebrauchen, greife ich zu Floats.
Dein Typ wiederum macht nach einiger Überlegung - sorry ;) - überhaupt keinen Sinn mehr. Schon 8² schlägt bei deinem 8-Bit-Beispiel durch einen Überlauf fehl, durch deinen Shiftfaktor werden die festen Fixed-Point-Grenzen unkontrollierbar - abhängig von dem Binärwert und dem Faktor (eigentlich wohl eher Exponent ;) ) - hin- und hergeschoben. Die Verwendung des Typs ist damit quasi unmöglich, Float Types (und das _ist_ dein Typ einfach, wie du schon selbst am Schluss erwähnt hast) sind ohne normierte Mantisse einfach unsinnig und unbrauchbar. |
Re: Spezielle Festkommazahl?
Hallo Khabarakh,
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Wo ist der Überlauf?
int1 := 8;
int2 := 8; Shift := 0; erg := int1 * int2; // am Shift-Faktor ändert sich nix, da 0+0=0 ist... Zitat:
Zitat:
Zum Verwendungszweck: - Float: Immer, wenns geht - Festkomma ohne variablen Shift-Faktor: Mir fällt kein sinnvolles Einsatzgebiet ein - Festkomma mit variablem Schiebefaktor: wenn keine FPU da is Letzterer Punkt impliziert zwar schon, dass es unter Delphi, was ja nur unter Win läuft und Win nur mit FPU funktioniert, wenig Sinn macht auf Floats zu verzichten, aber das war ja auch schon gesagt... mfg Christian |
Re: Spezielle Festkommazahl?
Zitat:
Zitat:
Zitat:
Ganz egal, welchen Shiftfaktor ich wähle, spätestens nach achtfacher Multiplikation mit 1 (!) ist bei 8-Bit Schicht im Schacht. Zitat:
Es gibt sicher ein paar Anwendungsgebiete für "Shifted Fixed Points", aber da dabei wohl zu jeder Zeit die Anzahl der Operationen, die Wertebereiche aller Argumente bekannt sein müssen, sind die Gebiete imho schon ziemlich eingeschränkt. Warum sonst sollte ein dem Dreidimensionalem durchaus mächtiger Handheld wie z.B. der Nintendo DS ausschließlich Fixed Point benutzen, wenn sich Grafikprogrammierer am PC eine Welt ohne Floatpoint gar nicht mehr vorstellen können (und ja, die Theorie der Fließkommazahlen steckt tief im Design heutiger PC-Engines)? |
Re: Spezielle Festkommazahl?
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Hier nochmal n Beispiel, warum es sinnvoll ist den Shilftfaktor zu benutzen:
Delphi-Quellcode:
Wir können also damit rechnen. Hätten wir die - impliziten - Shiftfaktoren nicht, gäb es keine Möglichkeit damit zu rechnen, da entweder der große ider der Kleine Wert nicht in die 16Bit passt...
// Voraussetzungen:
// - keine FPU da // - es ist genau bekannt in welchen Wertebereichen die gemessenen Größen sich befinden // - es stehen nur 16-Bit-Datentypen zur Verfügung var // zur Verdeutlichung SmallInt; man kann also mit 16 Bit rechnen: Wert1: SmallInt; // sehr große Zahl; 2^10 bis 2^14; Wert2: SmallInt; // sehr kleine Zahl; 2^-9 bis 2^-6 Erg: SmallInt; Shift: SmallInt; begin // Wir wollen beide Werte multiplizieren; Mit Float kein Problem, aber das steht nicht zur Verfügung... Wert1 := GetWert1(Sonstwoher); // Wertebereich bekannt. Impliziter Shiftfaktor -10; unser Beispielwert sei 128 * 2^12 = 512 * 2^10(das 10^10 wird implizit gespeichert durch den impliziten Shiftfaktor) Wert2 := GetWert2(Sonstwoher); // Wertebereich bekannt. Impliziter Shiftfaktor +10; unser Beispielwert sei 4 * 2^-7 = 8 * 2^-6 Erg := Wert1 * Wert2; // 128 * 4 = 512 Shiftfaktor := 4; // 10 - 6 // muss nicht extra gespeichert werden, da er implizit bekannt ist. Wichtig is aber ne gute Dokumentierung end; Ich weiß, das is alles ganz anders, als unter Delphi. Und das is nur ein Beispiel. Bei der programmierung für n 16-Bit-DSP gilt nämlich u.a.: - es gibt nur 16 Bit. fertig - jede Mikrosekunde zählt - Division is verboten - Wer durch Konstanten teilt, wird geteert und gefedert - Wer durch 2er-Potenzen teilt, wird gevierteilt - Die bedingten Sprünge(u.a. die berühmt-berüchtigten ifs) werden in den Tartaros verbannt, wo sie tagein tagaus versuchen einen Stein auf einen Hügel... ähm... ne das macht schon Sisyphos... müssen uns also noch ne geeignete Strafe einfallen lassen :gruebel: So isses also auf m DSP zumindest so ungefär. Die Strafen könnten auch noch härter sein. Bin mir da nicht sicher... Zitat:
Zitat:
mfg Christian |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz