IntToBin

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

IntToBin

Beitrag von Maik81ftl »

Moin Moin,

Bin gerade über eines meiner Testprogramme, welches dazu dient Funktionen zu testen.

Dabei ist mir aufgefallen, das Lararus bei folgender Function Immer mit der Meldung kommt

Code: Alles auswählen

Ausführung Beendet.

Code: Alles auswählen

Function DezToBin(Value: pChar):pChar; cdecl;
var Count: Integer;
    A: Integer;
    Temp: String;
begin
     Temp:= '';
     Count:= Length(Value);
     for A:= 0 to Count do
        Temp:= Temp+IntToBin(StrToInt(Value[a]), 8, 0);
     result:= pChar(Temp);
end;
Besteht die möglichkeit, das die Function IntToBin einen Fehler enthält oder rufe ich diese nur falsch auf?

Ziel dieser Function auf dem Dezimalen wert von A (65) einen Binären Datenstrom zu erzeugen.

Dieser soll nach o.g. Function so aussehen. 6 = 00000110; 5 = 00000101.

zusammen sollen beide werte den gesammtstring '0000011000000101' ausgeben.

wenn hierbei dennoch ggf ein Bug vorliegen sollte, werd ich das wohl zu fuß machen müßen.

via PN bitte ich im fall des falles um Info, wie man einen Bug meldet.

Danke im Vorraus
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: IntToBin

Beitrag von MAC »

interessant.
Aber wenn das deshalb nen .dll nutzt, nur wegen der funktion, dann würd ich folgendes benutzen:

Code: Alles auswählen

function InttoBin(aint:integer;bits:integer = 32):string;
function InttoBin(aint:integer;bits:integer = 32):string;
var
i:integer;
puffer:integer;
begin
result := '';
puffer := aint;
for i := bits-1 downto 0 do
    begin
    if puffer >= 2**i then // für ** wird unit math benötigt... ist standartmäßig dabei.
       begin
       result := result + '1';
       puffer := puffer - 2**i;
       end
      else
       begin
       result := result + '0';
       end;
   end;
end;
so ungefähr sollte das aussehen und alle probleme mit pchar sind weg :mrgreen: .
Ach ja, die fuktion ist gerade aus dem kopf geschrieben , deshalb könnten fehler drinn auftauchen...
Zum beispiel behandelt das nicht den fall für negative zahlen- da müsste man bits auf 31 setzen und am anfang testen ob die zahl < 0 ist. Dann währe das erste bit von links eine 1 , andernfals eine 0.
Wahrscheinlich geht es sogar noch schneller mit shl...
Zuletzt geändert von MAC am Di 15. Mär 2011, 20:12, insgesamt 1-mal geändert.

Code: Alles auswählen

Signatur := nil;

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: IntToBin

Beitrag von Maik81ftl »

MAC hat geschrieben:interessant.
Aber wenn das deshalb nen .dll nutzt, nur wegen der funktion, dann würd ich folgendes benutzen:

Code: Alles auswählen

function InttoBin(aint:integer;bits:integer = 32):string;
var
i:integer;
puffer:integer;
begin
result := '';
puffer := aint;
for bits-1 downto 0 do
    begin
    if puffer > 2**i then // für ** wird unit math benötigt... ist standartmäßig dabei.
       begin
       result := result + '1';
       puffer := puffer - 2**i;
       end
      else
       begin
       result := result + '0';
       end;
   end;
end;
so ungefähr sollte das aussehen und alle probleme mit pchar sind weg :mrgreen: .
Ach ja, die fuktion ist gerade aus dem kopf geschrieben , deshalb könnten fehler drinn auftauchen...
Zum beispiel behandelt das nicht den fall für negative zahlen- da müsste man bits auf 31 setzen und am anfang testen ob die zahl < 0 ist. Dann währe das erste bit von links eine 1 , andernfals eine 0.
Wahrscheinlich geht es sogar noch schneller mit shl...
Functionrückgabe als String??? damit wäre ich wieder bei dem Thema, das ich nur schwer String's bei *.so übergeben kann.

Aber danke für den Rest. des versuch ich mal.

und da du sagst, nur für diese Function? nene, in der .so solle einige functionen gesammelt werden.
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: IntToBin

Beitrag von Maik81ftl »

String bzw pChar ist wie ich grade gesehen habe egal. Programm wird erst mal normal gefahren, allerdings die Rüchgabe ich lehr. :(
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: IntToBin

Beitrag von carli »

Das Problem ist, dass der Pchar auch nur auf den Speicher des Strings verweist.

Die beste Lösung wäre, dass du die .so das Ergebnis in einen Buffer mit Maximallänge hineinschreiben lässt.
Zuletzt geändert von carli am Mi 16. Mär 2011, 18:42, insgesamt 1-mal geändert.

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: IntToBin

Beitrag von MAC »

jap, jetzt hast du wieder das problem mit strings, aber wenn das die einzige funktion ist die du aus der .so brauchst , dann wärst du ja jetzt unabhängig von dieser. Kommt also drauf an was du der .SO übergeben willst...

edit: > zu >= geändert - schleife korrigiert...

Code: Alles auswählen

Signatur := nil;

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: IntToBin

Beitrag von Maik81ftl »

MAC hat geschrieben:jap, jetzt hast du wieder das problem mit strings, aber wenn das die einzige funktion ist die du aus der .so brauchst , dann wärst du ja jetzt unabhängig von dieser. Kommt also drauf an was du der .SO übergeben willst...

edit: > zu >= geändert - schleife korrigiert...
nun ich darf sagen! dank euch porblem gelöst :D

Hab mir die Function in das Testprojekt übernommen, umgeschrieben und siehe da. alle Info#s, die ich Brauche kommen. :mrgreen:

function schaut nach Obtimierung nun so aus.

Code: Alles auswählen

function DeztoBin(aint:integer;bits:integer = 32):pChar;  cdecl;
var
B:integer;
puffer:integer;
a: String;
begin
result := '';
puffer := aint;
for B:= bits downto 0 do
    begin
    if puffer mod 2 = 0 then
       begin
       Puffer:= puffer div 2;
       a:= '0'+a;
       end
    else
        begin
        puffer:= Puffer div 2;
        a:='1'+a;
        end;
    end;
    result:= pChar(A);
end;
nur noch die zeichenlänge von 32 auf 7 runter schrauben und Wandlung ist perfekt.

Danke MAC für die schnelle vorlage.
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: IntToBin

Beitrag von MAC »

stimmt, div und mod ist noch besser...
Kein problem.

Code: Alles auswählen

Signatur := nil;

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: IntToBin

Beitrag von Maik81ftl »

MAC hat geschrieben:stimmt, div und mod ist noch besser...
Kein problem.
kenn ich auch noch aus anderen Sprachen. Deine ging zwar auch soweit, aber so issen auch für andere Besser zu lesen :D

Das ergebnis könnt ihr wenn ihr wollt hier lesen und zurückwandeln :D
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

Eclipticon
Beiträge: 292
Registriert: Sa 5. Feb 2011, 20:38
OS, Lazarus, FPC: Windows XP VirtualBox (FPC 2.6.4, Laz 1.2.4)
CPU-Target: 32Bit
Wohnort: Wien

Re: IntToBin

Beitrag von Eclipticon »

Alternativ koennte man sowas verwenden:

Code: Alles auswählen

function DecToBin(AInt: integer; Bits: integer = 32): string;
const
  BinaryStrings: array[$0..$f] of string =
    ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
    '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
  a: string = '';
begin
  Assert(Bits mod 4 = 0, 'Bits mod 4 <> 0');
  repeat
    a    := BinaryStrings[AInt and $0000000F] + a;
    AInt := AInt shr 4;
    Bits := Bits - 4;
  until (Bits <= 0);
  Result := A;
end;
In einem ersten kurzen Test war dieser Code bei 1e6 Zyklen > 6x schneller als der vorhin vorgeschlagene.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: IntToBin

Beitrag von Socke »

Eclipticon hat geschrieben:In einem ersten kurzen Test war dieser Code bei 1e6 Zyklen > 6x schneller als der vorhin vorgeschlagene.
Ist ja auch klar, da du immer in vier Bit großen Blöcken arbeitest. Daher musst du bei 32 Bit nur 32 / 4 = 8 Mal den Ergebnisstring neu erstellen (anstatt 32 Mal). Noch schneller könnte es gehen, wenn man den Ergebnisstring auf die maximale Größe (32 Zeichen) initialisiert und dann mittels eines Index die einzelnen Buchstaben setzt und am Ende nicht benötigte Zeichen vorne wieder herauskürzt.

Übrigens: In deinem Fall, ist es theoretisch egal, ob Bits ein Vielfaches von 4 ist. Wenn es das nicht ist, tauchen am Anfang des Strings maximal drei Nullen auf.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: IntToBin

Beitrag von Maik81ftl »

Eclipticon hat geschrieben:Alternativ koennte man sowas verwenden:

Code: Alles auswählen

function DecToBin(AInt: integer; Bits: integer = 32): string;
const
  BinaryStrings: array[$0..$f] of string =
    ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
    '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
  a: string = '';
begin
  Assert(Bits mod 4 = 0, 'Bits mod 4 <> 0');
  repeat
    a    := BinaryStrings[AInt and $0000000F] + a;
    AInt := AInt shr 4;
    Bits := Bits - 4;
  until (Bits <= 0);
  Result := A;
end;
In einem ersten kurzen Test war dieser Code bei 1e6 Zyklen > 6x schneller als der vorhin vorgeschlagene.
:lol: ist zwar schöner gestatet und kürzer, aber ob das nun bei 1⁶ Zyklen schneller ist als meine variante spielt bei einem Datensatz von max. 500 Zeichen leine große rolle, solange die CPU schnell genug ist.

werd ihn aba dennoch bei meiner nächten einheit DezToHex versuchen. :D
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

Antworten