![]() |
Re: Zufallszahl generieren
Ich finde, das wäre eine Diskussion in einem eigenen Thread wert.
|
Re: Zufallszahl generieren
Nein ein Typecast ist, wenn du einen Datentyp mit Gewalt und / oder Compiler Magic in einen anderen umwandelst. Zum Beispiel:
Delphi-Quellcode:
Mit den Funktionen IntToStr, FloatToStr, usw. wird eine "normale" Typumwandlung gemacht.
str := PChar(s);
Zitat:
|
Re: Zufallszahl generieren
Das ist deine Interpretation!
Typecast heißt nichts anderes wie Type Conversion heißt nichts anderes wie Typenumwandlung! ALLES was IRGENDWIE einen Datentyp in einen anderen umwandelt, ist ein Typecast! |
Re: Zufallszahl generieren
Zitat:
|
Re: Zufallszahl generieren
Ein Cast kann natürlich auch weich sein:
Delphi-Quellcode:
<Float> := <Integer>;
|
Re: Zufallszahl generieren
Zitat:
|
Re: Zufallszahl generieren
Zitat:
nein, dies sind implizite Type Casts. Für einen expliziten gibt man den Typ an. Btw: was hat das ganze mit einer Zufallszahl zu tun? :glaskugel: |
Re: Zufallszahl generieren
Zitat:
Delphi-Quellcode:
var
myfloat: float; myint: integer; begin myint := 3; myfloat := myint; end; |
Re: Zufallszahl generieren
Zitat:
|
Re: Zufallszahl generieren
Moin Moin NamenLozer,
und was möchtest Du damit sagen? :gruebel: bpsw.
Delphi-Quellcode:
i ist ein integer,
s: string;
i: Integer; begin i := 12345; s := IntToStr(i); // s = '12345'; s ist ein string inttostr übernimmt einen integer und gibt einen string zurück. Hier werden zwei implizite Casts gemacht (i = integer und s = string) wobei diese jedoch den selben Typ besitzen und daher keine Konvertierungen vorgenommen werden. Bei der Zuweisung i = integer, gilt das oben gesagt, ebenfalls kein expliziter Cast. Wo liegt denn das Verständnisproblem? :gruebel: |
Re: Zufallszahl generieren
Um auch mal meinen Senf dazuzugeben:
Das ganz oben (auf dieser Seite) sind für mich keine impliziten Typecasts. Explizit ist sowas wie var := PChar(string); Implizit etwas wie double := floatvar; es wird konvertiert, aber man muss es nicht sagen und inttostr sind nützliche Hilfsfunktionen, die einem einen integer in eine lesbare Form wandeln. (in .net vll. besser gelöst, da bringt jede Zahl ihre toString() Methode gleich mit ^^) Zitat:
|
Re: Zufallszahl generieren
Zitat:
Inttostr ist für mich kein Typecast, sondern eine Funktion. Nach deiner Defintion wäre ja jede Funktion, deren Rückgabewert von einem anderen Typ ist als der oder die Eingabeparameter, ein Typecast. Dannw wäre also auch sowas nach deiner Definition ein Typecast:
Delphi-Quellcode:
[edit]Wäre nett, wenn jemand das Thema splitten könnte[/edit]
function IsNegative(Value: integer): Boolean;
begin result := Value > 1; end; ... if IsNegative(3) then ... // <-- Typecast? IMO nicht |
Re: Zufallszahl generieren
Zitat:
|
Re: Typecast or not?
Ich habe diesen Thread von
![]() |
Re: Zufallszahl generieren
Moin!
Zitat:
Ein Konvertierung wandelt vorhandene Daten und erzeugt neue. Diese können zwar wieder auf die Originale Speicherstelle abgelegt werden, aber die zugrunde liegenden Daten dienen als Ausgangspunkt für eine explizite Arbeitsanweisung. //EDIT: Einschub Anfang - Beispiel in elektronischer Form - Ein Integer liegt im Speicher in seiner binären Form vor, also eine Basis von 2 und das linear hintereinander. Um diesen mit der Basis von 10 auszugeben, muss er konvertiert werden und ist mit einer Basis von 10 nicht mehr binär als Integer im System speicherbar, da dieses fest mit der Basis von 2 arbeitet. Somit muss zwangsweise ein Typ her, der die Daten mit der Basis von 10 aufnehmen kann, also ein String. Gleiches gilt für die BCD Kodierung, welche zwar auch die Basis von 2 nutzt, aber eine anderen Einteilung hat. Hintergrund ist hierbei, dass pro Stelle 6 mögliche Werte ungenutzt bleiben (1 Nibble pro Dezimalstelle = 4 Bit = 2^4 = 16 Kodierungsmöglichkeiten von denen nur 0..9, also 10 Möglichkeiten genutzt werden). Die hexadezimale Schreibweise nutzt das volle Nibble zur Darstellung. Ok, damit haben wir 4 Bits, also 4 digitale Steuerleitungen die 0 & 1 sein können. Wenn ich diese nun ausgeben will, dann kann ich 4 Leuchtdioden nehmen und man kann den Wert ablesen. Hier ist kein Typecast nötig, alles 1:1 verdrahtet. Pro Bit eine LED - passt. Wenn ich nun aber eine 7 Segmentanzeige habe, dann habe ich nun die Möglichkeit für einen Typecast und einer Konvertierung, da ich 4 Ausgänge habe aber 7 Eingänge an der Anzeige. Eine Konvertierung wäre ein 4-zu-7 Dekoder. Dieser hat einen Eingang von 4 Signalen und 7 Ausgangssignale und der konvertiert die Signale entsprechend. Alles angeschlossen und die Anzeige zeigt die BCD Wert an. Abhängig vom 4-zu-7 Dekoder kann sie auch die hexadezimale Darstellung. Und nun zum Typecast: ein Typecast wäre hier nun die 4 Leitungen an 4 Segmente der Segmentanzeige zu legen. Die 3 noch nicht beschalteten Eingänge kann man nun freilassen oder man schaltet welche zusammen. Dies wäre ein Typecast, weil man sagt, er soll die 4 Leitungen als 7 Leitungen betrachten. Die Anzeige wird dann schöne Symbole anzeigen, aber selten was was verständliches. Abhängig von der Beschaltung kann das geübte Auge wieder die 4 Ausgänge den LEDs der Segmente zuordnen und man wäre wieder beim ersten Beispiel mit der 1:1 Beschaltung auf 4 LEDs. //EDIT: Einschub Ende Alles was in Delphi mit Compilermagic gemacht wird, ist meistens eine Konvertierung. Die Compilermagic selbst fügt diese Konvertierung hinzu. Wäre keine Konvertierung nötig, wäre auch kein Compilermagic nötig. Ein Beispiel für eine strukturierten Cast wäre eine Union, welche u.a. in Delphi auch genau für einen Typecast eingesetzt wird.
Delphi-Quellcode:
Der Int64Rec beinhaltet eine Definition um ein und die selbe Speicherstelle in einer Größe von 8 Byte unterschiedlich zu betrachten. Einmal in Form von 2 DWords und einmal in Form von einem Int64. Die Daten im Speicher werden nicht konvertiert, es werden keine neuen Daten erzeugt. Die Zugriffe auf Int64Rec.Hi bzw. Int64Rec.Lo sind Zugriffe direkt auf die Bytestellen des lInt64. Die Union definiert nur eine Menschenlesbare Form bzw. Definition von Byte Offsets.
var
lHighDWord, lLowDWord: LongWord; lInt64: Int64; begin lInt64 := $1234567890abcdef; lHighDWord := Int64Rec(lInt64).Hi; lLowDWord := Int64Rec(lInt64).Lo; end; Ein anderer Fall mit Compilermagic:
Delphi-Quellcode:
Hier wird intern eine Konvertierung durchgeführt: der Compiler erweitert eine Ganzzahl um den fraktionalen Teil und macht ihn zu einer Fliesskommazahl. Der Wert an sich wird (eigentlich) nicht verändert, aber es ist eine Konvertierung, da aus den alten Daten (lInt) neue Daten (lDouble) generiert werden.
var
lDouble: double; lInt: integer; begin lInt := 4556; lDouble := lInt; end; Ein anderer Fall, harter Typecast, keine Compilermagic:
Delphi-Quellcode:
Ohne den typecast wird der Delphicompiler korrekterweise meckern, da die Typen unterschiedlich und nicht zuweisungskompatibel sind. Der type-cast wiederrum macht keine Konvertierung - aus der TObject Instanz wird keine TStrings Instanz. Hier sagt man dem Compiler nur: ich weiss, das ist ein TObject, aber ich sage dir: betrachte es als TStrings Typ. Da TStrings zu TStrings typengleich sind, hat der Compiler nichts dagegen. Er macht es, aber es wird nichts konvertiert bzw. überprüft.
var
lHigherObject: TStrings; lBaseObject: TObject; begin lBaseObject := TObject.Create; lHigherObject := TStrings(lBaseObject); end; Der ordentliche Weg wäre hier eine Überprüfung der Typen, aber das ist in diesem Beispiel mal keine Compilermagic sondern versteckt sich in einem Operator (bzw. zwei, da AS IS beinhaltet). Das bei dem Beispiel nichts konvertiert wurde ist einfach zu sehen beim Zugriff auf die von TStrings eingeführten Methoden und Eigenschaften. Ein oft genutzter typecast ist auch die Vorzeichenbehaftung zu entfernen. Beispiel:
Delphi-Quellcode:
Der Compiler warnt hier, dass er extra Code eingeführt hat, da der Vergleich so nicht gut durchführbar ist. Er warnt über den Vergleich von signed und unsigned Werten. Er sagt auch, dass er beide Werte erweitert hat. Der Programmierer will hier die Zahlenwerte vergleichen und Delphi erkennt das Dilemma, denn lUnsigned kann Werte bis 4,2 Milliarden annehmen, aber dafür keine unter 0 und lSigned nur bis 2,1 Milliarden, aber das mit und ohne Vorzeichen. Delphi kann nun aber schlecht den lSigned zu einem unsigned machen um es zu vergleichen, weil dann würden alle negativen Zahlen wegfallen. Auch kann er den lUnsigned nicht zu einem signed machen, dann würden alle Werte über 2,1 Milliarden wegfallen. Also erweitert er beide auf den nächst grösseren Typ und vergleicht denn. Um die Warnung wegzubekommen greifen viele Programmierer aber schnell mal zu typecast:
var
lSigned: LongInt; lUnsigned: LongWord; begin lSigned := -1; lUnsigned := $ffffffff; if lSigned = lUnsigned then ; end;
Delphi-Quellcode:
Und dabei tritt dann genau das oben genannte Problem auf: Die negativen Zahlen falle weg. In diesem Falle wäre hier sogar von Gleichheit auszugehen, da die binäre Form von -1 eines signed 32 Bit Wertes so aussieht, dass das MSB gesetzt ist (Bit 31) (Vorzeichen Bit) und alle anderen Bits negiert sind. Somit wäre es bei -1 genau $ffffffff. Somit würde ein Vergleich der oben nach der Korrektur von Delphi mit der Erweiterung noch fehlschlägt bei einem Typecast richtig sein. Hier sieht man vor allem, dass Delphi hier keine Konvertierung der Daten vornimmt sondern einfach den Speicherinhalt neu interpretiert bzw. betrachtet mit der aufgezwungenen Brille eines unsigned dwords.
var
lSigned: LongInt; lUnsigned: LongWord; begin lSigned := -1; lUnsigned := $ffffffff; if LongWord(lSigned) = lUnsigned then ; end; Und zu den Dingen bezüglich harter und weicher Cast, so wäre dies am besten auch in C++ erklärbar (dynamic_cast<>() && static_cast<>()), wobei Delphi sich da nichts nimmt (IS && TXXXX()). Und explizit und impliziter Cast: explizit bedeutet, es muss unbedingt was angegeben werden, damit ein Cast gemacht wird. Somit ist der explizite Cast durch die Schreibweise mit neuen Type gut erkennbar. Dieser kann, muss aber keine Compilermagic beinhalten. Ein impliziter Cast wiederrum benötigt keine Angabe von Typen oder extra Code sondern die Konvertierung wird still und heimlich durchgeführt. Dieser beinhaltet meist die Verwendung von Compilermagic. MfG Muetze1 |
Re: Typecast or not?
Ok meine Definition:
Impliziter typecast: Ein Word wird als Cardinal interpretiert, ohne dass man das selbst angibt. ebenso Integer -> Floattyp (wobei es hier eine tatsächliche Umwandlung gibt) Expliziter typecast: alles, wo explizit ein Speicherbereich anders interpretiert wird Byte(aCardinal) Pointer(aInt) Cardinal(P) PMyRecord($00FFAACC) generelle Typenumwandlung: Funktionen die einen Typ umwandeln. :roll: IntToStr(), StrToInt, StrToFloat(), was es halt so gibt und was man auch selbst schreiben könnte. Der Unterschied zwischen StrtoInt und einem expliziten typecast ist für mich also, ob dadurch Bytecode generiert werd, der etwas macht (streng gibt es den bei impliziten casts mitunter auch). [Edit] roter Kasten |
Re: Typecast or not?
Um die Frage noch mal hochzuholen: Behaupten kann man ja viel, aber gibt es für eure Interpretationen des Wortes Typecast auch irgendwelche unterstützenden Quellen?
|
Re: Typecast or not?
Ein Typecast ist meiner Meinung nach nichts anderes als den Inhalt der angegeben Variable, bzw. Speichers als den angegeben Typen zu interpretieren.
IntToStr etc. sind reine Typumwandlungen. |
Re: Typecast or not?
Moin!
1. Diese Umwandlung wird so genannt. Was willst du als Quelle haben? Eine Übersetzung? ![]() ![]() 2. @quendolineDD: Du widersprichst dir selbst. Gerade bei deinem Beispiel IntToStr() wird nicht der Speicher anders interpretiert, sondern du rufst eine Funktion auf, die das ganze verarbeitet. Der Speicherinhalt wird nicht anders interpretiert sondern dargestellt. Du teilst auf der Basis 10 Speicherstellenwert auf x viele Bytes auf, wovon eines gerade mal einen Wertebereich von '0' bis '9' nutzt. Was wird denn dort anders interpretiert? Eine andere Interpretation des Speichers an der Stelle des Integers (und damit ein Typecast), wäre folgendes:
Delphi-Quellcode:
Damit sagst du: das ist kein Integer, das ist ein String!
var
lInt: integer; lStr: string; begin lInt := 1234; lStr := string(lInt); end; Und mit IntToStr() sagst du: Ich will diesen Integer bitte in der dezimalschreibweise dargestellt haben. Gleiche skannst du binär, hex oder einer sonstigen Basis haben. MfG Muetze1 |
Re: Typecast or not?
Zitat:
(Wie es eben beispielsweise auch bei Wiki steht :tongue: ) |
Re: Typecast or not?
Zitat:
Nach dieser Definition ist jede Funktion aus dem Schema eine Typumwandlung. Auch z.B. Sign(). Sie wandelt die Zahl in einen Aufzählungstyp. :wall: Zitat:
Die eigentliche Umwandlung - also auch auf die du dich hier beziehst zur dezimalen Darstellung, sprich IntToStr() - geschieht in Wikipedia gar nicht und wird selbst im Beispiel gar nicht angerissen bzw. überhaupt drauf hingewiesen. Es geht dort um die Typumwandlung. |
Re: Typecast or not?
Ein Typecast ist nicht nur eine Umwandlung, sondern die Interpretation eines Speicherinhaltes.
Steht an einer Speicheradresse der Wert 33, ist das als Byte betrachtet 33 und als Char/String(bei folgendem Wert 0) '!' Eine Umwandlung per IntToStr Funktion würde '33' ergeben [Edit: Text korrigiert. Meine Tastatur springt immer im Text :( ] |
Re: Typecast or not?
Was bedeutet "Chalung" :?:
|
Re: Typecast or not?
Zitat:
Code:
Wo bitte geschieht denn hier noch eine Typumwandlung - außer durch die Funktion int2byte??
int i = 100;
byte b = int2byte( i ); Zitat:
Als Beispiel für Typumwandlung wird übrigens genau das genannt: Zitat:
|
Re: Typecast or not?
Der Unterschied ist wie ich oben schon zu erklären wollte ( leider wurden dort 2 Sätze vermischt) dass
-beim Cast ein Inhalt einer Speicherstelle als ein anderer Typ interpretiert wird: 33 -> '!' -bei der Umwandlungsroutine eine Wert in eine andere Form gewandelt wird: 33 -> '33' |
Re: Typecast or not?
@mkinzler: Die Begriffe "Cast" und "Umwandlung" sind aber äquivalent :cry:
|
Re: Typecast or not?
Imho nicht
|
Re: Typecast or not?
Zitat:
![]() oder eben mal wieder Wiki Zitat:
|
Re: Typecast or not?
Ja, wie wir es sagen. Nach IntToStr() enthält der Speicher mit dem String andere Daten als der Speicher mit dem Integer. Also ist es eine Umwandlung. Ein Typecast impliziert, dass der Inhalt des Speichers gleich bleibt.
|
Re: Typecast or not?
Zitat:
|
Re: Typecast or not?
Zitat:
Was die Informatikprofessoren dazu sagen: unterschiedlich, aber am häufigstens die gleiche Ansicht wie mkinzler und ich. Und da es nun genug Quellen gibt die es mal ein hü und die anderen als hott bezeichnen, können wir das Spielchen noch lange so weiter treiben. Grundlegend ist eine Unterscheidung zwischen Typecast und Umwandlung im täglichen Informatikergebrauch ein viel genauerer und damit präzisere Ausdrucksweise möglich. Es ist rein datentechnisch betrachtet ein gehöriger Unterschied und wenn der nicht klar ist, kann es leicht zu nicht funktionierenden Code kommen. ABER: wenn einem der Unterschied egal ist bzw. man alles über einen Kamm schert und es sich erlauben kann, weil man es z.B. nie so detailliert betrachten muss, dann kann man auch beides als gleich ansehen und keinen Unterschied dazwischen machen. Der Kamm wäre hierbei typecast und drüber scheren tust du zum einen eine neu-Interpretation der Daten sowie eine Veränderung der Daten. Jeder wie er will - wir sind ein freies Land. |
Re: Typecast or not?
Zitat:
Während ein InttoStr in etwa sowas macht (legt jetzt keine Adresse in EAX und ist unsigned, aber habs grad noch da);
Delphi-Quellcode:
//Int <= High(Cardinal), 32-bit mit 32-bit Division, 35 Bytes Code
procedure MyInttoStr4(Int: Cardinal; P: PByte); asm //Parameter: EAX: Int, EDX: P push ebx mov ebx, edx xor ecx, ecx // ecx = 0 push cx // 16-bit Strinendezeichen auf den Stack mov cx, 10 @Start: xor edx, edx // edx = 0 div ecx //EAX: Ganzzahl, EDX: Rest; EDX:EAX / ecx add dl, 48 //ascii zahlencode in dl ('0': 48) push dx //ascii-code sichern or eax, eax // ganze Zahl auf 0 testen jnz @Start // wenn eax nicht 0 wiederholen @WriteBuffer: pop dx // ascii zurück mov byte [ebx], dl //ascii in den Buffer inc ebx //Bufferzeiger eins weiter or dl, dl //auf Stringende prüfen jnz @WriteBuffer pop EBX //ret wird automatisch am Ende erzeugt end; |
Re: Typecast or not?
Meflin, IntToStr interpetiert eine Zahl als String. Genauso wie diese hier:
Delphi-Quellcode:
Das ist kein Typecasting, sondern eine -ich wiederhole mich- Interpretation einer Zahl als folge arabischer Ziffern. Ebensogut könnten wir römische Ziffernfolgen, Maya-Glyphs oder ähnliche textuelle Repräsentationen von Zahlen verwenden. Das hat nichts mit Konvertierung im Sinne des Wiki-Artikels zu tun. Und schon gar nicht mit Typecasting.
function DecToRoman(Decimal: Longint): string;
const Numbers: array[1..13] of Integer = (1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000); Romans: array[1..13] of string = ('I', 'IV', 'V', 'IX', 'X', 'XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M'); var i: Integer; begin Result := ''; for i := 13 downto 1 do while (Decimal >= Numbers[i]) do begin Decimal := Decimal - Numbers[i]; Result := Result + Romans[i]; end; end; Der Wiki-Artikel ist unglücklich formuliert, weil er zunächst Type conversion mit Type cast gleichsetzt. Nach unserem Verständnis ist eine Konvertierung eine Überführung in einen anderen Datentyp, nach meinem Verständnis eben auch in den Datentyp 'Römische Zahlen als String'. Ich glaube, in diesem Verständnis liegt Dein Problem, meins übrigens auch. Ich musste den Artikel mehrmals lesen, um diesen Unterschied zwischen meinem Verständnis einer Konvertierung und dem im Wiki-Artikel zu verstehen. Im Übrigen ist der englische Artikel hier etwas genauer, aber unglücklich finde ich die Formulierung auch. Für völlige Verwirrung würde übrigens der Einwand führen, das SQL hier Deine Definition nahelegt, zumindest Microsoft:
SQL-Code:
:stupid:
select cast (1 as varchar(10))
|
Re: Typecast or not?
Ich schließe mich an mkinzler und muetze1 an. Bei einem Typecast wird der Compiler angewiesen ein ihn unter einem bestimmten Typ bekannten Speicherbereich als einen anderen Typ zu benutzen ohne das der Speicher verändert wird.
Bei einer Umwandlung a la IntToStr wird ein Speicherbereich als Typ Integer interpretiert und ein neuer Speicherbereich angelegt in dem das Resultat der Konvertierung geschrieben wird. Was mir hier aber noch aufgefallen ist. Ich würd davon abraten Typecasts a la Type(Var) zu verwenden sondern stattdessen (Var as Type) oder falls es ein Pointer auf ein TObject ist (TObject(Pointer) as Type) zu verwenden da der Compiler euch dann vor falschen Zuweisungen bewahrt. |
Re: Typecast or not?
Ich denke, das hängt von der Situation ab. Die Benutzung von as generiert zusätzlichen Code zur Fehlerüberprüfung, oder?
|
Re: Typecast or not?
Ja, das kostet natürlich ein paar CPU Zyklen. Hat mir dafür aber schon so manche längere Bugsuche erspart. Gerade in größeren Projekten bei denen mehrere Leute dran arbeiten halte ich es für sinnvoll. Aber Du hast schon recht, es kommt drauf an was man machen will. Mir ist ein leicht langsameres Programm lieber als eines das ab und an abstürzt ;)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:43 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 by Thomas Breitkreuz