Konwersja stringu w HEX na double

Konwersja stringu w HEX na double
CB
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 4 lata
  • Postów:13
0

Mam plik tekstowy w formacie WKB, w którym są zapisane 8 bajtowe liczby typu double.
Ale nie są zapisane po ludzku, czyli jak np. 123.45, tylko jako obraz bitowy liczby w.g. IEEE 754 (znak, cecha, mantysa, jak w asemblerze) w hexach, np:

The X co-ordinate is 2.0
000000000140000000000000004010000000000000
The Y-co-ordinate is 4.0
000000000140000000000000004010000000000000

Czy sa w Delphi jakieś funkcje biblioteczne, które mogą pomóc w konwersji takiej liczby na double?

cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Poznań
  • Postów:8774
0

CB
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 4 lata
  • Postów:13
0
cerrato napisał(a):

Tak na szybko - czy ten link rozwiązuje problem?
https://www.codeproject.com/Questions/99483/Convert-value-by-IEEE-754-protocol

Niestety, wygląda na to,że z Delphi nie ma dostępu do tego obiektu BitConverter

cerrato
ja chyba jeszcze zaspany jestem (w końcu jesteśmy przed południem), wybacz ;)
PD
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 8 godzin
2

może to rozwiąże Twój problem:https://github.com/Tominator2/HEXtoIEEE-754


pozdrawiam
paweld
AK
Tak chorego kodu to dawno nie widziałem.
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1

Oba powyższe rozwiązania bazują na liczbach pojedynczej precyzji.
Projekt z GitHub pewnie łatwiej będzie przerobić na double.

AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:12 dni
  • Postów:3561
0

Wybaczcie pytanie delphistycznej blondynki.

To nie ma w D żadnych środków aby

  • wczytać hex string do tablicy bajtów
  • w/w tablicę zinterpretować jako double, rzutowanie, unia, czy jak tam nazywacie ...

Bo C to najlepszy język, każdy uczeń ci to powie
Zobacz pozostały 1 komentarz
AK
W normalnych językach programowania to kilka linii technicznego kodu, bez doktoratów. Biblioteka? Moze tak jak w JS, biblioteka do sklejania stringów albo mnożenia liczb?
flowCRANE
1. można na różne sposoby; 2. można rzutowaniem.
ME
To Delphi, tutaj tak się nie robi, tylko się instaluje komponent niewizualny TConvertHexString na formę a potem wywołuje tConvertHexString1.Convert(value) no i wypluwa wynik. Co nie znaczy, że w Pascalu nie da się napisać tych 3 linijek, ale to chodzi o mentalność bardziej. Takie rozleniwienie komponentami, czasem absurdalne.
flowCRANE
Bez przesady. Zresztą nawet jeśli byłaby to prawda, to mnogość komponentów wg mnie jest atutem, nie wadą. Natomiast jeśli deweloperzy każdą pierdołę implementowaliby w ten sposób (komponentami), to źle to by o nich świadczyło, a nie o samej technologii. No ale komponentowy mit pozostał i dalej potrafi śmieszyć. ;)
ME
Technologia jak technologia. Ważne to, jak się z niej korzysta, a ten mit jednak nie wziął się tak całkiem znikąd
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1

Można ew. jeszcze spróbować z ASM:
Konwersja zmiennych IEEE 754

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Tuchów
  • Postów:12167
0

A co z konwersją na UInt64 i rzutowaniem na Double? Można też Move zrobić zamiast rzutowania.

Edit: jednak nie – te koordynaty w postaci hex nie pasują rozmiarowo do szesnastkowego UInt64. Pozostaje po prostu mała funkcja, która przekonwertuje fragmenty ciągu na inty i zbuduje liczbę rzeczywistą. Czyli to co podał @Paweł Dmitruk – bez zbędnych warunków i komentarzy zostanie 10 linijek kodu.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
obscurity
  • Rejestracja:około 6 lat
  • Ostatnio:4 minuty
2

Jesteś pewny że to w ogóle dobre wartości? Po pierwsze mają po 21 bajtów co jest dość dziwnym rozmiarem dla typu liczbowego, po drugie podałeś dwa razy ten sam ciąg a mają one niby reprezentować różne wartości

edit: wygooglałem wklejony ciąg do googla

https://mariadb.com/kb/en/well-known-binary-wkb-format/

zgubiłeś pogrubienia:

  • The first byte indicates the byte order. 00 for big endian, or 01 for little endian.
  • The next 4 bytes indicate the geometry type. Values from 1 to 7 indicate whether the type is Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, or GeometryCollection respectively.
  • The 8-byte floats represent the co-ordinates.

Czyli tylko "4000000000000000" reprezentuje "2.0" a "4010000000000000" reprezentuje "4.0"
Nie znam pascala (ostatni kod w nim pisałem jakieś 16 lat temu) ale pół minuty w googlach wystarczy żeby znaleźć:

https://ideone.com/GDQZfu

Kopiuj
uses sysutils;

var
  xi : int64;
  yi : int64;
  x: double absolute xi;
  y: double absolute yi;
begin
	xi := StrToInt64('$4000000000000000');
	yi := StrToInt64('$4010000000000000');
	writeLn(x); // 2.0
	writeLn(y); // 4.0
end.

"A car won't take your job, another horse driving a car will." - Horse influencer, 1910
edytowany 8x, ostatnio: obscurity
flowCRANE
O to właśnie chodzi.
CB
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 4 lata
  • Postów:13
0

Dziękuję za pomoc.
Dla potomności pozostawiam elegancką funkcję:

Kopiuj
function HexToDouble(txt:String):Double;
var
  xi : int64;
  x: double absolute xi;
begin
  xi := StrToInt64('$'+txt);
  result:=(x);
end;

Sposób użycia: HexToDouble('4000000000000000') da wynik 2.0

edytowany 1x, ostatnio: flowCRANE
AK
Coś mi to nie gra, przynajmniej jeśli w hexie jest to, co POWINNO być.
obscurity
@AnyKtokolwiek: a co tam powinno być? @coder-bis: możesz od razu dać xi: int64 absolute Result jak w przykładzie poniżej, wtedy nie musisz już przepisywać x do result
AK
wykładnik, mantysa? ja tego nie widzę tutaj. Ciąg bajtów pod floatem to nie int odpowiedniej długości.
obscurity
to jest w hexie - masz 0x4000000000000000 czyli znak 0, wykładnik 10000000000b, mantysa 0b czyli 1 = 1 * 1 * 2^1 = 2.0
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Tuchów
  • Postów:12167
1

Dziwnie to wygląda. Masz przykład funkcji konwertujących we Free Pascalu – sprawdź czy w Delphi zadziała:

Kopiuj
function DoubleToString(const AValue: Double): String; inline;
var
  Cast: Int64 absolute AValue;
begin
  Result := '$' + HexStr(Cast, SizeOf(Cast) * 2);
end;

function StringToDouble(const AValue: String): Double; inline;
var
  Cast: Int64 absolute Result;
  Dummy: Integer;
begin
  Val(AValue, Cast, Dummy);
end;

Test użycia:

Kopiuj
var
  ValueAsString: String;
  ValueAsDouble: Double = Pi;
begin
  WriteLn('Double: "', ValueAsDouble:2:16, '"');

  ValueAsString := DoubleToString(ValueAsDouble);
  WriteLn('String: "', ValueAsString, '"');

  ValueAsDouble := 0;
  WriteLn('Double: "', ValueAsDouble:2:16, '"');

  ValueAsDouble := StringToDouble(ValueAsString);
  WriteLn('Double: "', ValueAsDouble:2:16, '"');
end.

I wyjście konsoli:

Kopiuj
Double: "3.1415926535897931"  // wartość początkowa – tutaj Pi
String: "$400921FB54442D18"   // ciąg znaków po konwersji liczby zmiennoprzecinkowej
Double: "0.0000000000000000"  // wyzerowana wartość (żeby nie było że optymalizator wyciął numer)
Double: "3.1415926535897931"  // wartość po konwersji ciągu na liczbę zmiennoprzecinkową

Perfekcyjne odwzorowanie poprzedniego stanu.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
obscurity
przecież to dokładnie to samo tylko zamienione "StrToInt64" na "Val"
AK
Test dla liczb z wykładnikiem zero. A dla innych?
flowCRANE
@obscurity: ale w dwie strony i z przykładem użycia, niech zostanie dla potomnych. @AnyKtokolwiek: każda liczba przejdzie – w końcu i tak jest rzutowana na Int64, więc nie ma znaczenia, nawet jeśli będzie tam NaN czy Infinity.
obscurity
@AnyKtokolwiek: tam nie ma wykładnika zero. Tu https://gregstoll.dyndns.org/~gregstoll/floattohex/ możesz sobie zobaczyć jak double jest zakodowany na bitach
CB
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 4 lata
  • Postów:13
0

Skoro jesteście tak chętni do pomocy, to może pomożecie mi w pracy detektywistycznej, rozkminienia tego formatu WKB
W pliku dostaję coś takiego:

0
0103000020840800000100000012000000B93313FCCDC61D418692C981207423415342B0EAFFC31D4140DD40A937742341728BF9091DC11D4138D7307B4F7423413D0D18A[....]

Z tego co sam doszedłem,
0 - zignorować
w stringu dwa pierwsze znaki 01 - to oznacza litle endian
0300 0020 8408 0000 0100 0000 1200 0000 - następne 32 znaki to jakiś nagłówek, bo we wszystkich plikach się powtarza podobny. W nim zgaduję, że 0100 - oznacza, że w pliku jest jakiś wielokąt (to się zgadza, powinna być granica działki), 1200 - to pewnie liczba wierzchołków ($12 czyli 18 wierzchołków)
dalej powinny być wspólrzędne, po kolei x y x y 18 razy
Zatem pierwsza liczba to B93313FCCDC61D41, ale jej konwersja ww. funkcją daje wynik ~-3,67 E-33, czyli bez sensu. Powinna być rozsądna liczba rzędu paruset tysięcy.
Macie jakiś pomysł co może być źle? Może ze względu na little endian trzeba poprzestawiać któreś bajty?

AK
Zgadywanka bez założeń? To by nie miało sensu. Ale ty chyba znasz jakieś założenia, a my nie, mamy zgadywać?
obscurity
  • Rejestracja:około 6 lat
  • Ostatnio:4 minuty
1

Tak przy 01 masz little endian czyli musisz odwrócić wszystkie bajty, przykładowo B93313FCCDC61D41 = 411DC6CDFC1333B9 - jako float by to było 487859.49616699998 ale nie wiem czy to prawidłowy fragment.
Nie ma tu co zgadywać - WKB to standard - sprawdź czy ten tool online potrafi to rozkodować:
https://rodic.fr/blog/online-conversion-between-geometric-formats/
korzysta z bilbioteki w js https://github.com/cschwarz/wkx
Może uda Ci się znaleźć coś do delphi, ale jeśli nie to zawsze możesz się wspomóc źródłami tej biblioteki żeby napisać własny kod

Tu masz jakąś funkcję do odwracania bajtów jako wstawka asm:

Kopiuj
function BSwap64(I: QWORD): QWORD; { inline; }
asm
        MOV     EDX,[EAX]
        MOV     EAX,[EAX+4]
        BSWAP   EAX
        BSWAP   EDX
end;

Swoją drogą strasznie głupi standard który marnuje bajt na zapisanie informacji o endianness zamiast go po prostu... ustandaryzować


"A car won't take your job, another horse driving a car will." - Horse influencer, 1910
edytowany 2x, ostatnio: obscurity
CB
Dzięki, po odwróceniu bajtów działa
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)