Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Bitmuster eines Single Berechnen (https://www.delphipraxis.net/127557-bitmuster-eines-single-berechnen.html)

Corpsman 15. Jan 2009 12:11


Bitmuster eines Single Berechnen
 
Hossa ich will das Bitmuster eines singles berechnen und als String ausgeben

dabei habe ich mir gedacht mache ich das so :

Delphi-Quellcode:
Function BinFtoString(d: single): String;
Var
  i, j: integer;
  k: ^integer;
Begin
  result := '';
  k := @d;
  j := k^;
  For i := 0 To 31 Do Begin
    If (j And $70000000 = $70000000) Then
      result := result + '1'
    Else
      result := result + '0';
    j := j Shl 1;
  End;
End;
nur kommt da leider nicht das Richtige raus, habt ihr ne Idee ?

hazard999 15. Jan 2009 12:19

Re: Bitmuster eines Single Berechnen
 
Du weist schon das ein single ein floatingpoint datentyp ist?

Wikipedia:

Zitat:

Berechnung einer IEEE single precision Gleitkommazahl (32-Bit-Gleitkommazahl) [Bearbeiten]

Hier werden die genauen Rechenschritte vorgestellt, um eine Dezimalzahl in eine binäre Gleitkommazahl vom Typ Single nach IEEE 754 umzuwandeln. Dazu müssen nacheinander die drei Werte (Vorzeichen v (1 bit), Mantisse m und Exponent e) berechnet werden, aus denen sich die Zahl x zusammensetzt:

x = (-1)^v \cdot m \cdot 2^e

Vorzeichen

Je nachdem, ob die Zahl positiv oder negativ ist, ist das Vorzeichen v +1 oder −1. Ein positives Vorzeichen wird mit einem Vorzeichenbit 0 gespeichert, negative Zahlen werden durch eine 1 im Vorzeichenbit gekennzeichnet.

Alle weiteren Berechnungen erfolgen mit dem Betrag der Zahl.

Exponent

Als nächstes wird der Exponent gespeichert. Beim IEEE single-Datentyp sind dafür 8 Bit vorgesehen. Der Exponent muss so gewählt werden, dass die Mantisse einen Wert zwischen 1 und 2 erhält:

e = \left \lfloor \log_2(|x|) \right \rfloor

Wenn hierbei ein Wert für den Exponenten heraus kommt, der kleiner −126 oder größer 127 ist, kann die Zahl mit diesem Datentyp nicht gespeichert werden. Statt dessen wird die Zahl als 0 (Null) oder als „unendlich“ abgespeichert.

Der Wert für den Exponenten wird jedoch nicht direkt gespeichert, sondern um einen Bias-Wert erhöht, um negative Werte zu vermeiden. Bei IEEE single ist der Bias-Wert 127. Somit werden die Exponentenwerte −126…+127 als so genannte „Charakteristik“ zwischen 1…254 gespeichert. Die Werte 0 und 255 als Charakteristik sind reserviert für die speziellen Zahlenwerte „Null“, „Unendlich“ und „NaN“.

Mantisse

Die Mantisse wird nun in den verbleibenden 23 Bit abgespeichert:

m = \left( \frac{|x|}{2^e} - 1 \right) \cdot 2^{23}

Zahlenbeispiel mit der Zahl 11,25

Zahl = +11,25

Vorzeichen = + -> 0binär

\mathrm{Exponent} = \left \lfloor \log_2(11{,}25) \right \rfloor = \left \lfloor 3{,}49 \right \rfloor = 3 --> 3 + 127 = 130 -> 10000010binär

\mathrm{Mantisse} = \left( \frac{11{,}25}{2^3} - 1 \right) \cdot 2^{23} = (1{,}40625 - 1) \cdot 2^{23} = 3407872 -> 01101000000000000000000binär

Damit ergibt sich folgende Gleitkommazahl einfacher Genauigkeit:

0 10000010 01101000000000000000000

Umkehrung

Will man aus einer Gleitkommazahl im Maschinenwort (32 Bit) eine Dezimalzahl errechnen so kann man dieses mit folgender Formel recht schnell erledigen:

Z=(-1)^{VZ}\cdot(1{,}0+M/2^{23})\cdot 2^{E - 127}

generic 15. Jan 2009 12:20

Re: Bitmuster eines Single Berechnen
 
Dez. 7 = Bin. 111

Du solltest dort eine 8 verwenden.

des weiteren versuch mal den Datentyp cardinal Anstelle von integer.

Corpsman 15. Jan 2009 12:20

Re: Bitmuster eines Single Berechnen [gelöst ]
 
Ja das Weis ich, und genau das will ich ja auch ;)

so gehts :

Delphi-Quellcode:
Function BinFtoString(d: single): String;
Var
  i: integer;
  k: ^integer;
  j: integer absolute d;
Begin
  result := '';
  For i := 0 To 31 Do Begin
    If j And 1 = 1 Then
      result := '1' + result
    Else
      result := '0' + result;
    j := j Shr 1;
  End;
End;
@ generic

thx mit 8 statt 7 gehts auch ;)

Delphi-Quellcode:
Function BinFtoString(d: single): String;
Var
  i, j: integer;
  k: ^integer;
Begin
  result := '';
  k := @d;
  j := k^;
  For i := 0 To 31 Do Begin
    If (j And $80000000 = $80000000) Then
      result := result + '1'
    Else
      result := result + '0';
    j := j Shl 1;
  End;
End;

himitsu 15. Jan 2009 13:01

Re: Bitmuster eines Single Berechnen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Statt Integer lieber LongInt oder LongWord verwenden (Single ist 4 Byte ... Integer ist es nicht unbedingt)

Delphi-Quellcode:
Function BinFtoString(f: Single): String;
Var i: Integer;
  b: LongInt absolute f;

Begin
  SetLength(Result, 32);
  For i := 32 downto 1 do Begin
    Result[i] := Char((b and 1) + Ord('0'));
    b := b shr 1;
  End;
End;

Function BinFtoString(f: Single): String;
Var i: Integer;
  b: PLongInt;

Begin
  b := @f;
  SetLength(Result, 32);
  For i := 32 downto 1 do Begin
    Result[i] := Char((b^ and 1) + Ord('0'));
    b^ := b^ shr 1;
  End;
End;

Corpsman 15. Jan 2009 15:40

Re: Bitmuster eines Single Berechnen
 
der Himitsu macht wieder die GAnz elegante Variante ;).

Du nutzt die Sprachspezifikation voll aus, auf solche Ideen würde ich ja erst gar nicht kommen. sieht auf jeden richtig cool aus der source .

Aber wenn ich deinen Source sehe grad noch ne andere Frage :
Wenn ich
Delphi-Quellcode:
var S:String[10];
Deklariere mache ich das ja weil ich eine Statische Variable haben will die dann immer Gleich groß ist.

Nur kann ich in meinem Projeckt dann nicht einfach auf s[5] zugreifen. Das Geht erst wenn ich vorher

Delphi-Quellcode:
Setlength(s,10);
gemacht habe. Weis Jemand was das dann soll ?

Klar zum Lesen/ Schreiben in Streams müste es noch was Bringen, aber wieso mus ich trotzdem noch das Setlength machen ?

Wenn ich ein Statisches Array mache und ne Variable von dem Typ mache mus ich ja auch kein Setlength mehr mit angeben.

Sir Rufo 15. Jan 2009 15:46

Re: Bitmuster eines Single Berechnen
 
wegen weil der Null-Terminierung von Strings!

himitsu 15. Jan 2009 15:57

Re: Bitmuster eines Single Berechnen
 
String[10] gibt 'nen ShortString an, welcher maximal 10 Zeichen enthalten kann ... aber ein ShortString hat noch 'nen LängenByte und das steht anfangs auf 0 (keine Zeichen enthalten)

du kannst da entweder Array[0..9] of Char verwenden, oder mußt halt (z.B. per SetLength) die Länge noch definieren

[add]
ups: doch keine 0 am Anfang ... ein ShortString wird nicht initialisiert ... heißt, es kann da auch vollkommener Schrott drinstehn.

Delphi-Quellcode:
Var S: String[10];

S[0] := #2; // Index null entspricht der Position des Längenbytes
            // das entspricht also SetLength(S, 2);
S[1] := 'a';
S[2] := 'b';
S[9] := 'x';
S = 'ab'
bei ShortString gibt es keine Terminierung mit #0 ... da zählt nur die Angabe im Längenbyte

[add2]
zum Testen:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
Var S: String[10];

begin
  SetLength(S, 4);
  S[1] := 'a';
  S[2] := 'b';
  S[4] := 'd';
  S[9] := 'x';
  Label1.Caption := s;
end;
im Labem steht nun 'ab#d' (# ist ein zufälliges Zeichen)

Corpsman 15. Jan 2009 19:06

Re: Bitmuster eines Single Berechnen
 
Vielen Dank himitsu

das macht es etwas verständlicher.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:29 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