AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Generic Integer zu Float konvertieren

Ein Thema von Zacherl · begonnen am 22. Dez 2017 · letzter Beitrag vom 22. Dez 2017
Antwort Antwort
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:04
Delphi-Version: 10 Berlin
Hallo zusammen,

ich habe einen generischen Record der Form type TMyRec<T: record> mit den Spezialisierungen type TMyURec = TMyRec<UInt8/Uint16/UInt32> und type TMyIRec = TMyRec<Int8/int16/Int32> . Ich möchte nun eine implizite Konvertierung vom generischen Typ zu Single/Double implementieren.

Gibt es hier eine elegante Möglichkeit, ohne den konkreten generischen Typ zu ermitteln? Einfach alles in den größtmöglichen Integer Typen zu kopieren und dann zu konvertieren ist leider keine Möglichkeit, da ich wissen muss, wie das Vorzeichen zu behandeln ist.

Momentan tendiere ich dazu einfach zwei "Basis-Records" zu definieren; Einen für unsigned und Einen für signed. Das bedeutet allerdings einiges an dupliziertem Code.

Viele Grüße
Zacherl
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:18

Gibt es hier eine elegante Möglichkeit, ohne den konkreten generischen Typ zu ermitteln? Einfach alles in den größtmöglichen Integer Typen zu kopieren und dann zu konvertieren ist leider keine Möglichkeit, da ich wissen muss, wie das Vorzeichen zu behandeln ist.
Tuts da nicht trotzdem ein record -> Int64 -> Double?
Vorzeichen bleiben erhalten und alles ist gut?!

Oder kommst an den Wert des Record mit High und Low ran?
Dann könntest du im Falle das Low(DeinRecord.Value) < 0 entsprechen agieren.

Delphi-Quellcode:
var
  x1: UInt16;
  x2: Int16;
begin
  Writeln(High(x1));
  Writeln(Low(x1));
  Writeln(High(x2));
  Writeln(Low(x2));
  Readln;
end.
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#3

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:25
Delphi-Quellcode:
function TMyRec<T>.ToDouble: Double;
begin
  case GetTypeData(TypeInfo(t)).OrdType of
    otSByte: Result := PShortInt(@v)^;
    otUByte: Result := PByte(@v)^;
    otSWord: Result := PSmallInt(@v)^;
    otUWord: Result := PByte(@v)^;
    otSLong: Result := PInteger(@v)^;
    otULong: Result := PCardinal(@v)^;
  end;
end;
Edit: Das soll natürlich PWord sein bei otUWord
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (22. Dez 2017 um 13:46 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#4

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:31
Tuts da nicht trotzdem ein record -> Int64 -> Double?
Habe die 64-bit Typen in meinem Originalpost vergessen Da würde es dann leider nicht funktionieren.

Delphi-Quellcode:
function TMyRec<T>.ToDouble: Double;
begin
  case GetTypeData(TypeInfo(t)).OrdType of
    otSByte: Result := PShortInt(@v)^;
    otUByte: Result := PByte(@v)^;
    otSWord: Result := PSmallInt(@v)^;
    otUWord: Result := PByte(@v)^;
    otSLong: Result := PInteger(@v)^;
    otULong: Result := PCardinal(@v)^;
  end;
end;
Das wäre von der Idee her perfekt, aber ist das intrinsisch, oder erzeugt das Runtime-Overhead?
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#5

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:40
Delphi-Quellcode:
function TMyRec<T>.ToDouble: Double;
begin
  case GetTypeData(TypeInfo(t)).OrdType of
    otSByte: Result := PShortInt(@v)^;
    otUByte: Result := PByte(@v)^;
    otSWord: Result := PSmallInt(@v)^;
    otUWord: Result := PByte(@v)^;
    otSLong: Result := PInteger(@v)^;
    otULong: Result := PCardinal(@v)^;
  end;
end;
Das wäre von der Idee her perfekt, aber ist das intrinsisch, oder erzeugt das Runtime-Overhead?
Leider bisschen runtime overhead.
Wenn du genau weißt, dass dein T nur von den 6 System Typen ist und nicht von irgendwelchen Redeklarationen a la type TColumnIndex = type Integer dann kannst du auch das hier schreiben - TypeInfo vergleiche werden seit XE7 zur Compilezeit aufgelöst (kannst auch beides kombinieren so, dass du schnell bist, wenns Integer, Byte etc ist und wenn nicht auf die langsamere Variante zurück fällst)

Delphi-Quellcode:
function TMyRec<T>.ToDouble: Double;
begin
  if TypeInfo(T) = TypeInfo(ShortInt) then
    Result := PShortInt(@v)^
  else if TypeInfo(T) = TypeInfo(Byte) then
    Result := PByte(@v)^
  else if TypeInfo(T) = TypeInfo(SmallInt) then
    Result := PSmallInt(@v)^
  else if TypeInfo(T) = TypeInfo(Word) then
    Result := PWord(@v)^
  else if TypeInfo(T) = TypeInfo(Integer) then
    Result := PInteger(@v)^
  else if TypeInfo(T) = TypeInfo(Cardinal) then
    Result := PCardinal(@v)^
  else if TypeInfo(T) = TypeInfo(UInt64) then
    Result := PUInt64(@v)^
  else if TypeInfo(T) = TypeInfo(Int64) then
    Result := PInt64(@v)^
  else
    case GetTypeKind(T) of
      tkInteger:
        case GetTypeData(TypeInfo(t)).OrdType of
          otSByte: Result := PShortInt(@v)^;
          otUByte: Result := PByte(@v)^;
          otSWord: Result := PSmallInt(@v)^;
          otUWord: Result := PWord(@v)^;
          otSLong: Result := PInteger(@v)^;
          otULong: Result := PCardinal(@v)^;
        end;
      tkInt64:
        if GetTypeData(TypeInfo(T)).MinInt64Value = 0 then
          Result := PUInt64(@v)^
        else
          Result := PInt64(@v)^;
    end;
end;
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (22. Dez 2017 um 13:50 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:56
Tuts da nicht trotzdem ein record -> Int64 -> Double?
Habe die 64-bit Typen in meinem Originalpost vergessen Da würde es dann leider nicht funktionieren.
Nehme doch einen Int128!

Spaß beiseite, das muss doch elegant auch mit Low(deinRecord.Value) < 0 gehen (falls meine zweite Idee im Post untergegangen ist)!
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#7

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 13:58
Tuts da nicht trotzdem ein record -> Int64 -> Double?
Habe die 64-bit Typen in meinem Originalpost vergessen Da würde es dann leider nicht funktionieren.
Nehme doch einen Int128!

Spaß beiseite, das muss doch elegant auch mit Low(deinRecord.Value) < 0 gehen (falls meine zweite Idee im Post untergegangen ist)!
Er will doch die Konvertierung in den Record einbauen, und Low auf T geht nunmal nicht.
In Delphi generics geht leider das meiste nicht elegant, weils nunmal keine C++ Templates sind, denen das herzlich egal wäre,
wenn aus der Menge aller im Universum möglichen Typen für T welche nicht mit Ord funktionieren, solang du nur solche nutzt, bei denen das geht.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (22. Dez 2017 um 14:01 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 14:20
Er will doch die Konvertierung in den Record einbauen, und Low auf T geht nunmal nicht.
Ich hab das "implizite Konvertierung" überlesen.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Generic Integer zu Float konvertieren

  Alt 22. Dez 2017, 14:28
Danke euch beiden

Ich werde dann wahrscheinlich mal mit Stevies zweiter Variante probieren

In Delphi generics geht leider das meiste nicht elegant, weils nunmal keine C++ Templates sind, denen das herzlich egal wäre
Die C++ Templates sind tatsächlich das, was ich unter Delphi tatsächlich am meisten vermisse.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz