Ein binäres Problem

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Ein binäres Problem

    Hi !!

    Mir stellt sich mir folgendes Problem in den Weg. Ich habe ein Programm vor mir, dass seine Daten in einer binären Form in einer Datei liegen hat. Also so eine Art Datenbank. Ich soll es nun schaffen, die Daten aus der Binärdatei herauszu holen und in eine MySQL-DB zu übernehmen. Das ganze funktioniert auch schon! Nur war das eigentlich mehr zum angewöhnen an die Sache. Ich muss jetzt einen Weg finden die Daten aus der MySQL-DB zurück in die Binärdatei zu schreiben (also eine lauffähige Binärdatei erstellen). Das ganze ist dafür, dass eine Software ab und zu mit der Datenbank im I-Net abzugleichen. Die Pflege der Daten geschieht im I-Net, aber es gibt halt noch ein Programm, dass in Pascal geschrieben wurde und auch noch weiterhin vertrieben werden soll.

    Ich habe es auch schon geschafft eine lauffähige Version der Daten zu erstellen, aber da hab ich ein bischen getrickst. Es hapert an der Umwandlung von Fließkommazahlen ins Binäre format. Beim Auslesen der Datei hat man mir ein Beispiel-Script mitgegeben, dass in TCL geschrieben ist. Das brauchte ich sozusagen "einfach" nur in PHP übersetzen. Dort ist auch eine Funktion drin, die aus Binär-Daten eine Fließkommazahl erstellt. Leider ist das ganze aber ein bissel komplizierter wieder zurück zu rechnen.

    Hier mal die Binär -> Fliesskomma Funktion:
    PHP-Code:
    function convreal ($sixbytes) {
       
    $data = @unpack("cPOW/c4MANT/cMANTnull",$sixbytes);

       if(
    $data) {
         
    $real pow(2,($data[POW]+0x100)%0x100-129);
            if (
    $data[MANTnull]<0) {
                
    $real = -$real;
                
    $data[MANTnull] = abs($data[MANTnull]);
            }
            
    $div $real/128.0;
            
    $data[MANT5] = $data[MANTnull];
            for (
    $j 5$j>=1$j--) {
               
    $real $real+(($data["MANT".$j]+0x100)%0x100)*$div;
               
    $div $div/256.0;
            }
         
    $real round($real*100)/100.0;
       }
       else {
         
    $real 0;
       }
       return 
    $real;

    Der Funktion werden 6 Byte übergeben, indenen sich die Fließkommazahl befindet. Die Funktion unpack "extrahiert" aus diesen Bytes 6 Werte... ich geb mal ein paar Beispiele:
    Code:
    $data[POW] | $data[MANT1] | $data[MANT2] | $data[MANT3] | $data[MANT4] | $data[MANTnull] |
    -----------------------------------------------------------------------------------------------------
       -127    |       0      |        0     |       0      |       0      |        0        |   = 1
        127    |      51      |       51     |      51      |      51      |       51        |   = 0.35
       -127    |     -51      |      -52     |     -52      |     -52      |       12        |   = 1.1
        127    |       0      |        0     |       0      |       0      |        0        |   = 0.25
        127    |     -61      |      -11     |      40      |      92      |       15        |   = 0.28
       -128    |     102      |      102     |     102      |     102      |      102        |   = 0.9
       -128    |       0      |        0     |       0      |       0      |        0        |   = 0.5
    Vom Prinzip her muss ich "einfach" nur eine Funktion haben, die mir aus der Fließkommazahl, die einzelnen Array-Werte ($data) extrahiert.
    Hat wer ne' Idee?! Oder kennt wer irgendwelche Quellen indenen ich herausfinde nach welchen Spezifikationen Fließkommazahlen von Pascal geschpeichert werden? Für jeden Tip wäre ich dankbar!

    Gruss Jan
    www.traum-projekt.com

  • #2
    Tja ... mein TCL ist zwar arg eingerostet; aber wenn ich mich nicht irre:

    $data = @unpack("cPOW/c4MANT/cMANTnull",$sixbytes);
    ==>
    list($data[POW], $data[MANT], $data[MANTnull]) = explode('/', $sixbytes);
    for ($k=4; $k>=0; $k--, $data['MANT'] /= 10) $data["MANT$k"] = $data['MANT']%10;
    mein Sport: mein Frühstück: meine Arbeit:

    Sämtliche Code-Schnipsel sind im Allgemeinen nicht getestet und werden ohne Gewähr auf Fehlerfreiheit und Korrektheit gepostet.

    Kommentar


    • #3
      ups... mein Mailakkount aufdem die "Antworten" eingehen war/ist kaputt... Deshalb melde ich mich erst jetzt wieder.

      Das Script, was ich da oben geschrieben habe funzt. Das ist aus tcl in php "übersetzt". Das original tcl-Script sah so aus:
      Code:
      proc convreal {sixbytes} {
              binary scan $sixbytes cc4c pow mant mant0
              set real [expr {pow(2,($pow+0x100)%0x100-129)}]
              if ($mant0<0) {
                      set real [expr {-$real}]
                      set mant0 [expr {abs($mant0)}]
              }
              lappend mant $mant0
              set div [expr {$real/128.0}]
              for {set j 4} {$j>=0} {incr j -1} {
                      set real [expr {$real+(([lindex $mant $j]+0x100)%0x100)*$div}]
                      set div [expr {$div/256.0}]
              }
         expr {round($real*100)/100.0}
      }
      ...aber die ganze Sache hat sich jetzt erledigt. Ich hab die Umkehrfunktion nach tagelangem Suchen, hier und da etwas Hilfe fertig! Also das Format um das es sich bei Turbo-Pascal handelt nennt sich Real48. Die oben angegebene Funktion ist allerdings für PHP nicht ganz korrekt, da der Wert 0.0 und 1.0 nicht richtig behandelt wird. Aber hier einfach mal um die Sache abzuschliessen die Umkehrfunktion in PHP:
      PHP-Code:
      function setBit(&$array,$bit) {
        
      $i sizeof($array) - bcdiv($bit ) - 1;
        
      $array[$i] = ($array[$i]) | (<< ($bit ));
      }

      function 
      reconvreal($num) {

        
      $result = array(6);
        for (
      $n=0$n<6$n++) $result[$n] = 0// clear result

        
      if ($num == 0.0) return $result;

        
      // sign bit (47)
        
      if ($num 0setBit($result47);
        
      $num abs($num);

        
      // exponent 0-7
        
      $e 0;
        while (
      $num >= 2.0) { // normalize value (1.0 <= v < 2.0)
           
      $e++;
           
      $num $num 2.0;
        }
        while (
      $num 1.0) {
           
      $e--;
           
      $num $num 2.0;
        }

        
      // mantiassa
        
      $num $num 1.0// skip first bit, is always "1" and not stored
        
      for($n=0$n<39$n++) {
           
      $pow pow(2.0, (--$n));  // 2^-1, 2^-2, 2^-3 etc.
           
      if ($num >= $pow) {
              
      setBit($result46-$n);
              
      $num $num $pow;
           }
        }

        
      $e += 129// bias for pascal real type? (in IEEE = 127)

        
      for ($n=0$n<8$n++) { // set bits 0 to 7
           
      if (($e & (<< $n)) != 0setBit($result$n);
        }

      return 
      $result;

      Der Rückgabewert der Funktion ist ein Array indem die 6 Bytes enthalten sind. Allerdings von rechts nach links! und unsigned.
      Vielleicht brauchts ja irgendwer irgendwann mal...

      Gruss
      Jan
      Zuletzt geändert von LiOfAgony; 05.03.2003, 22:03.
      www.traum-projekt.com

      Kommentar

      Lädt...
      X