Entwickler-Ecke
Basistechnologien - Neuen Basistyp erstellen
VampireSilence - Do 02.12.10 22:13
Titel: Neuen Basistyp erstellen
Ich sitze aus rein experimentellen Gründen gerade daran, einen neuen Basistypen zu schreiben, und zwar einen Int128.
Dieser soll eben mit 128 Bits arbeiten und so weit ist das auch kein Problem - habe dazu einfach eine Klasse mit entsprechendem bool[128]-Array erstellt. Jetzt ist es aber leider so, dass ich 2 Variablen vom Typ Int128 nicht addieren kann, bzw. dass der Compiler dies nicht zulässt. Auch das einfache zuweisen einer Zahl ist nicht möglich. Mir ist klar, dass dies notwendig ist, da der Compiler ja nicht hinter ein komplexes Objekt schauen kann und deshalb wollte ich euch fragen, ob ihr dafür eine Lösung kennt.
mfg
- VampireSilence
Th69 - Fr 03.12.10 14:25
Hallo VampireSilence,
ein bool[128]-Array ist aber eindeutig der falsche Datentyp dafür. Nimm einfach zwei Int64 (long) und programmiere die entsprechenden Operatoren aus (+, - und * sollten ja recht einfach gehen, einzig für die Division '/' wirst du ein bißchen mehr überlegen müssen - erinnere dich an die Grundschulmathematik, nur daß du jetzt im Binärsystem rechnen mußt).
Zum Rechnen mit den Überträgen wirst du auch die Bitoperationen benötigen, s. z.B.
Bitoperationen in C# [
http://www.mycsharp.de/wbb2/thread.php?threadid=48671].
jaenicke - Fr 03.12.10 14:41
Es geht ja um experimentelle Zwecke, deshalb ist die Performance wohl egal. Deshalb ist das hier durchaus sinnvoll, weil man besser sehen kann, welche Bits gesetzt sind beim Debuggen.
Th69 - Fr 03.12.10 14:47
Ja, schön und gut, aber ein bool ist ja ein logischer Datentyp (also nur true und false). Wie soll man dem bool-Array dann eine Zahl zuweisen?
C#-Quelltext
1:
| bool[128] array = { false, ... , true }; |
So ???
Und dann damit auch noch rechnen...
Yogu - Fr 03.12.10 14:50
Wie wäre es mit einem impliziten Operator von int64 in den neuen Basistyp?
VampireSilence - Fr 03.12.10 20:26
@jaenicke
Danke, das ist genau das, was ich brauchte. Ist nur schade, dass ich den "="-Operator nicht überladen kann und somit eine direkte Zuweisung trotzdem nicht möglich ist.
@Th69
Du musst wissen, dass Zahlen binär nur aus wahr und falsch bestehen. Ein Int64 ist also auch nicht viel mehr, als ein bool[64]. Zwei davon zu einem Int128 zusammenzufügen, wäre also nur ein umständlicher Umweg. Da ein bool ein Bit repräsentiert, kann ich damit leichter arbeiten und warscheinlich ist es auch wesentlich performanter. Das rechnen damit funktioniert genau, wie im Dezimalen, nur dass 1 + 1 = 10 gilt. Eine Addition erfolgt demnach also bitweise (so wie es intern auch mit Int64 und Konsorten getan wird). Einem bool selbst kann keine Zahl zugewiesen werden, aber aus einer Folge von wahr und falsch, kannst du eine Zahl repräsentieren und auch eine dezimale Zahl darstellen. Dies erfolgt dann mit
Quelltext
1:
| Dezimalzahl = Bit[127] * 2 ^ 127 + Bit[126] * 2 ^ 126 + Bit[125] * 2 ^ 125 + Bit[124] * 2 ^ 124 + ... etc. |
mfg
- VampireSilence
jaenicke - Fr 03.12.10 20:40
VampireSilence hat folgendes geschrieben : |
| Danke, das ist genau das, was ich brauchte. Ist nur schade, dass ich den "="-Operator nicht überladen kann und somit eine direkte Zuweisung trotzdem nicht möglich ist. |
Sicher? Sind das nicht in dem Beispiel bei MS die ersten Operatoren? (Ich habe es aber nie ausprobiert.)
VampireSilence hat folgendes geschrieben : |
| Du musst wissen, dass Zahlen binär nur aus wahr und falsch bestehen. |
Das ist ihm sicher klar. ;-)
VampireSilence hat folgendes geschrieben : |
| Zwei davon zu einem Int128 zusammenzufügen, wäre also nur ein umständlicher Umweg. Da ein bool ein Bit repräsentiert, kann ich damit leichter arbeiten und warscheinlich ist es auch wesentlich performanter. |
Hier irrst du dich. Performanter ist es ganz bestimmt nicht. Denn so übernimmst du die ganzen bitweisen Operationen statt dies einfach dem Prozessor zu überlassen.
Zur echten Verwendung ist das mit dem Bool-Array nicht so gut geeignet, denn da kommt es dann doch eher auf Performance an.
Th69 - Fr 03.12.10 21:03
Und nicht zu vergessen: der Speicherplatz. Ein 'bool' belegt genau 1 Byte (8 bit), d.h. dein Datentyp wäre mindestens 128 Byte groß (anstatt bei zwei Int64 nur 16 Byte)...
Und VampireSilence, dein Satz
| Zitat: |
Ein Int64 ist also auch nicht viel mehr, als ein bool[64].
|
stimmt so also ganz und gar nicht!
jaenicke - Fr 03.12.10 21:13
Übrigens gibt es auch die BitArray Klasse bei .NET. Mal so nebenbei. ;-)
Yogu - Fr 03.12.10 21:30
VampireSilence hat folgendes geschrieben : |
| Ist nur schade, dass ich den "="-Operator nicht überladen kann und somit eine direkte Zuweisung trotzdem nicht möglich ist. |
Nein, es ist ein Segen, dass der Zuweisungsoperator nicht überladen werden kann! Das würde im reinen Chaos enden (siehe C++).
Was du brauchst, ist eine Umwandlung zwischen normalen Zahlentypen und deiner Klasse. Das geht mit den
implicit- und
explicit-Operatorn. Letztere erfordert es, dass der Datentyp, in den konvertiert werden soll, angegeben werden muss. Beim impliziten Operator passiert die Konvertierung ganz still und heimlich.
Die Konvertierung von
int und
int64 würde ich implizit machen, da keine Probleme auftreten können. Andersrum sollte es explizit sein, da die Zahl auch mal zu groß sein könnte, und dabei eine Exception geworfen werden muss.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| public static implicit operator Int128(int value) { }
public static explicit operator int(Int128 value) { } |
VampireSilence - Sa 04.12.10 14:50
Ok, mein Fehler lag also darin, anzunehmen ein bool wäre ein Bit. Das glaube ich euch jetzt auch einfach mal, aber mal ernsthaft: wofür zum Teufel braucht ein Datentyp, der sowieso nur wahr oder falsch speichert ACHT Bits ?! Was will man da bitte drin speichern ? ^^ Das ist doch die reinste Ressourcendekadenz.
@jaenicke
Ist die BitArray-Klasse nicht ein bisschen zu komplex und performancelastig dafür ?
| Zitat: |
| Hier irrst du dich. Performanter ist es ganz bestimmt nicht. Denn so übernimmst du die ganzen bitweisen Operationen statt dies einfach dem Prozessor zu überlassen. |
Sorry, aber das verstehe ich nicht. Selbstverständlich übernimmt der Prozessor meine Operationen, ich meine: was denn sonst ? Die Festplatte sicher nicht. Das klingt zugegeben etwas naiv, aber ich weiss es einfach nicht besser. Dazu fehlt mir das Hintergrundwissen.
@Topic
Ich werd dann wohl doch einfach 2 Int64 verbinden, das erscheint mir bisher die beste Lösung zu sein.
mfg
- VampireSilence
jaenicke - Sa 04.12.10 15:26
VampireSilence hat folgendes geschrieben : |
| aber mal ernsthaft: wofür zum Teufel braucht ein Datentyp, der sowieso nur wahr oder falsch speichert ACHT Bits ?! |
Wie willst du denn dem Prozessor oder dem Arbeitsspeicher einzelne Bits geben? ;-)
Stell dir nur mal vor der Speichermanager würde einzelne Bits reservieren.
Das wäre ein Overhead... ;-)
VampireSilence hat folgendes geschrieben : |
| Was will man da bitte drin speichern ? ^^ Das ist doch die reinste Ressourcendekadenz. |
False ist als Null definiert, alles andere als True.
Deshalb klappt auch der Vergleich mit True (if xy = true) in den meisten Sprachen nicht.
VampireSilence hat folgendes geschrieben : |
| Ist die BitArray-Klasse nicht ein bisschen zu komplex und performancelastig dafür ? |
Wahrscheinlich auch kaum mehr als dein Zugriff.
VampireSilence hat folgendes geschrieben : |
| Sorry, aber das verstehe ich nicht. Selbstverständlich übernimmt der Prozessor meine Operationen, ich meine: was denn sonst ? |
Beispiel (vereinfacht):
Du möchtest zwei Bytes addieren. Jetzt packst du die Bytes in die Register und schickst zusätzlich ein ADD als Assemblerbefehl zum Prozessor. Zack, ein Prozessortakt und du hast das Ergebnis.
Jetzt stell dir stattdessen vor du schickst die einzelnen Bits um das auszurechnen, was jeweils einen Takt mindestens braucht. Was meinst du wohl ist schneller? ;-)
VampireSilence - So 05.12.10 18:25
| Zitat: |
| Jetzt stell dir stattdessen vor du schickst die einzelnen Bits um das auszurechnen, was jeweils einen Takt mindestens braucht. Was meinst du wohl ist schneller? ;-) |
Ok, das ist natürlich einleuchtend. Ich hätte ja nicht ahnen können, dass das .NET Framework immernoch derartig umständlich mit den Daten umgeht, anstatt einfach alles in einem Takt zu verarbeiten. Man sollte meinen Microsoft hätte das in all den Jahren entsprechend optimiert, aber da war mein Optimismus wohl fehl am Platz. ^^
mfg
- VampireSilence
Yogu - So 05.12.10 18:46
VampireSilence hat folgendes geschrieben : |
| Zitat: | | Jetzt stell dir stattdessen vor du schickst die einzelnen Bits um das auszurechnen, was jeweils einen Takt mindestens braucht. Was meinst du wohl ist schneller? ;-) |
Ok, das ist natürlich einleuchtend. Ich hätte ja nicht ahnen können, dass das .NET Framework immernoch derartig umständlich mit den Daten umgeht, anstatt einfach alles in einem Takt zu verarbeiten. Man sollte meinen Microsoft hätte das in all den Jahren entsprechend optimiert, aber da war mein Optimismus wohl fehl am Platz. ^^ |
Da hast du was falsch verstanden.
Ein Wert vom Typ
int ist in einem 32-Bit-System in einer Speichereinheit gespeichert. Wenn nun zwei solche Zahlen addiert werden, werden sie beide als 32-Bit-Zahl weitergereicht, über einen elektronischen Baustein in einem Rutsch addiert, und das Ergebnis wieder irgendwo anders gespeichert. Normalerweise braucht eine CPU dafür einen Takt.
Wenn du nun einen 128-Bit-Typ erstellen willst und dafür ein
bool-Array verwendest, sieht der Speicher ganz anders aus: An einer Stelle steht ein Verweis auf eine andere Speicherstelle. Dort findet sich an erster Stelle die Anzahl der Einträge (128), und dann folgen 128 Byte, die jeweils 0 oder 1 enthalten. Insgesamt werden also (auf einem 32-Bit-System) 128 + 4 + 4 = 136 Byte belegt. Wenn du nun addieren willst, musst du das in C# selbst schreiben. Also: Du erstellst ein drittes Array mit 128 Bool-Werten (es müssen 132 Byte auf dem RAM reserviert werden). Dann addierst du die niedrigsten beiden Bits und speicherst sie in das Ergebnis-Array (Ein Bit laden, das andere Bit laden, addieren, speichern -> mindestens 4 Takte). Den Überlauf schreibst du in den zweiten Eintrag des Ergebnis-Arrays. Und das ganze musst du nun 128 mal machen. Was glaubst du, wie viele Takte dabei zusammenkommen?
.NET ist an sich überhaupt nicht langsam, und die Programme sind auch sehr gut optimiert. Allerdings simulierst du praktisch eine Recheneinheit des Prozessors, und das ist dann eben auch nicht besonders schnell.
Aber für das Verständnis sollte das überhaupt keine Rolle spielen; denn da kommt es schließlich nicht in erster Linie auf die Performance an.
Th69 - So 05.12.10 18:53
Das erinnert mich jetzt an eines meiner ersten großen Programme auf dem C-16. Dort hatte ich in BASIC (!) ein Programm namens "Prozessor" geschrieben, das die Assembler-Befehle emuliert -)
Leider reichte irgendwann der Speicher (16KB!!!) nicht mehr für das Programm aus, um alle Befehle umzusetzen (von der Geschwindigkeit will ich jetzt gar nicht mal reden :) )
VampireSilence - So 05.12.10 19:17
@Yogu
So wie du das erklärst, würde das aber bedeuten, dass man garkeine neuen Basistypen erstellen kann, sondern einfach nur (fast) alles danach aussehen lässt, obwohl hinter den Berechnung im Hintergrund etwas ganz anderes steckt. Es ist also in dem Falle notwendig den Int128 direkt im Prozessor zu implementieren, um einen "echten" davon deklarieren zu können. Oder auf deutsch: Ich kann mir die Finger blutig tippen, aber ein exaktes Äquivalent zu Int32 und Int64 wird es bis dahin niemals geben können.
mfg
- VampireSilence
jaenicke - So 05.12.10 19:22
VampireSilence hat folgendes geschrieben : |
| Oder auf deutsch: Ich kann mir die Finger blutig tippen, aber ein exaktes Äquivalent zu Int32 und Int64 wird es bis dahin niemals geben können. |
Das ist zwar richtig, aber du kannst dennoch einen performanten Ersatz schreiben. Nur musst du dann die vorhandenen 32-Bit bzw. 64-Bit Operationen des Prozessors auch nutzen. Und das kannst du nicht, wenn du für jedes Bit einzelne Berechnungen ausführst, die dann eben jeweils einzeln berechnet werden müssen.
Das ist wie wenn du ein Brot backen willst, das nicht in den Ofen passt. Jetzt kannst du entweder zwei halb so große Stücke backen und zu einem großen Brot zusammensetzen oder du kannst jede Scheibe einzeln backen. Was geht wohl schneller? ;-)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!