root66: Typumwandlung 2 x 16 Bit Word zu 1 x 32 Bit Fließkomma

Hallo,

ich habe zwei 16 Bit Words (0-65535) und möchte die zusammenkleben, so dass Javascript daraus eine Fließkomma-Zahl mit 32 Bit erkennt (Unsigned).

Wie geht das?

VG,
root66

  1. Hi,

    ich habe zwei 16 Bit Words (0-65535)

    Und wie „hast“ du die? Datentyp?

    und möchte die zusammenkleben, so dass Javascript daraus eine Fließkomma-Zahl mit 32 Bit erkennt (Unsigned).

    parseInt kennt einen radix-Parameter; parseFloat aber nicht.

    Und 32 Bit unsigned ist ungewöhnlich. Wenn du das haben willst, wirst du es dir selber basteln müssen.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
  2. Hi,

    ich habe zwei 16 Bit Words (0-65535) und möchte die zusammenkleben, so dass Javascript daraus eine Fließkomma-Zahl mit 32 Bit erkennt (Unsigned).

    mit Fließkomma meinst du IEEE single precision?
    Solche Typumwandlungen, bei denen einfach nur die speicher- oder prozessorinterne Repräsentation eines Datentyps als etwas anderes interpretiert wird, sind mit Javascript AFAIK nicht möglich.

    Wenn du etwas anderes meinst, solltest du dein Anliegen etwas präziser beschreiben.

    So long,
     Martin

    --
    ... und der FDP-Wähler gibt seine Stimme der FDP.
       (Faszinierende Erkenntnis meines Gemeinschaftskunde-Lehrers, 9. Schuljahr)
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. ich habe zwei 16 Bit Words (0-65535) und möchte die zusammenkleben, so dass Javascript daraus eine Fließkomma-Zahl mit 32 Bit erkennt (Unsigned).

      mit Fließkomma meinst du IEEE single precision?
      Solche Typumwandlungen, bei denen einfach nur die speicher- oder prozessorinterne Repräsentation eines Datentyps als etwas anderes interpretiert wird, sind mit Javascript AFAIK nicht möglich.

      Es handelt sich um eine Node.JS Applikation und Modbus, das ist ein Protokoll für SPS Hardware-Steuerungen.

      Ich kriege von dem Hardware-Gerät einen "REAL" Wert (32 Bit, unsigned) als zwei einzelne 16 Bit Word Werte (Signed 0-65535) geliefert. Die werden von dem Protokoll aufgeteilt und ich möchte die nun mit Node.JS wieder zusammensetzen. Der Javascript "number" Datentyp arbeitet intern auch mit 32 Bit.

      Ich hab es schon mit Bit-Operatoren versucht, in dem ich den ersten Wert um 16 Bit nach links verschoben habe und den zweiten dann rechts angehängt habe, aber das Ergebnis stimmt nicht mit dem richtigen Wert überein.

      1. Hallo,

        ich habe zwei 16 Bit Words (0-65535) und möchte die zusammenkleben, so dass Javascript daraus eine Fließkomma-Zahl mit 32 Bit erkennt (Unsigned).
        mit Fließkomma meinst du IEEE single precision?
        Solche Typumwandlungen, bei denen einfach nur die speicher- oder prozessorinterne Repräsentation eines Datentyps als etwas anderes interpretiert wird, sind mit Javascript AFAIK nicht möglich.

        Es handelt sich um eine Node.JS Applikation ...

        Davon habe ich bisher noch nicht gehört.

        und Modbus, das ist ein Protokoll für SPS Hardware-Steuerungen.

        Das ist mir allerdings ein Begriff.

        Ich kriege von dem Hardware-Gerät einen "REAL" Wert (32 Bit, unsigned) als zwei einzelne 16 Bit Word Werte (Signed 0-65535) geliefert.

        Nein. Die Fließkommaformate sind generell signed, deine beiden 16bit-Integers sind allerdings unsigned, wenn sie einen Wertebereich von 0..65535 haben. Das spielt aber hier auch keine Rolle.
        Wer allerdings so eine blöde Schnittstelle entwirft, gehört eigentlich geohrfeigt, bis er lacht. Und dann nochmal, weil er lacht.

        Die werden von dem Protokoll aufgeteilt und ich möchte die nun mit Node.JS wieder zusammensetzen. Der Javascript "number" Datentyp arbeitet intern auch mit 32 Bit.

        Ja, schon richtig, aber ...

        Ich hab es schon mit Bit-Operatoren versucht, in dem ich den ersten Wert um 16 Bit nach links verschoben habe und den zweiten dann rechts angehängt habe, aber das Ergebnis stimmt nicht mit dem richtigen Wert überein.

        Nein, kann es auch nicht. Mit dem, was du beschreibst, könntest du wieder einen 32bit-Integer bekommen. Aber kein Fließkommaformat. In Javascript kannst du noch so schön mit Zahlenwerten jonglieren, aber Integer bleibt Integer, oder wird höchstens in Floating Point mit dem gleichen Zahlenwert umgewandelt.

        Kurzum: Du kannst nicht byteweise oder bitweise auf das intern gespeicherte Format eines Fließkommawerts zugreifen - das wäre aber für eine solche Umwandlung notwendig. Du stehst vor einer Aufgabe, die meines Wissens in Javascript nicht lösbar ist.

        So long,
         Martin

        --
        Computer funktionieren grundsätzlich nicht richtig.
        Wenn doch, hast du etwas falsch gemacht.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Moin!

          Kurzum: Du kannst nicht byteweise oder bitweise auf das intern gespeicherte Format eines Fließkommawerts zugreifen - das wäre aber für eine solche Umwandlung notwendig. Du stehst vor einer Aufgabe, die meines Wissens in Javascript nicht lösbar ist.

          "nicht lösbar" würde ich nicht sagen, schließlich kriegen es andere Programmiersprachen ja hin, und auch Javascript ist turing-komplett - "irgendwie" wird es also gehen.

          Es geht nur nicht über den Hacker-Trick, zwei Integer-Werte in den Speicher zu schreiben und als Float-Wert wieder daraus auszulesen. Man muss sich eine Funktion schreiben, die die Umrechnung von Integer in IEEE-Float manuell vornimmt. Und das dürfte etwas komplizierter werden.

          - Sven Rautenberg

          1. Hallo,

            Du stehst vor einer Aufgabe, die meines Wissens in Javascript nicht lösbar ist.
            "nicht lösbar" würde ich nicht sagen, schließlich kriegen es andere Programmiersprachen ja hin, und auch Javascript ist turing-komplett - "irgendwie" wird es also gehen.

            ja okay, "irgendwie" schon. Aber mit gewissen Einschränkungen.

            Es geht nur nicht über den Hacker-Trick, zwei Integer-Werte in den Speicher zu schreiben und als Float-Wert wieder daraus auszulesen.

            Ich würde es nicht als Hacker-Trick bezeichnen, sondern eher als die natürliche Methode, wenn man einen Speicher- oder Registerinhalt einfach als etwas anderes interpretiert, als es ursprünglich gemeint war.

            Man muss sich eine Funktion schreiben, die die Umrechnung von Integer in IEEE-Float manuell vornimmt. Und das dürfte etwas komplizierter werden.

            Ja, zumal man auf diese Weise nur "korrekte" Werte gemäß IEEE 754 hinbekommt. Erhält man vom Remote-System aber fehlerhafte oder denormalisierte Werte, kann man sie nicht exakt rekonstruieren, man erhielte bestenfalls die gleichwertige normalisierte Darstellung oder NaN. Die Sonderfälle +INF und -INF kann man dagegen gezielt "herstellen", indem man einfach die entsprechenden Konstanten des Number-Objekts liest.

            Ciao,
             Martin

            --
            Wichtig ist, was hinten rauskommt.
              (Helmut Kohl, 16 Jahre deutsche Bundesbirne)
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Moin!

              Es geht nur nicht über den Hacker-Trick, zwei Integer-Werte in den Speicher zu schreiben und als Float-Wert wieder daraus auszulesen.

              Ich würde es nicht als Hacker-Trick bezeichnen, sondern eher als die natürliche Methode, wenn man einen Speicher- oder Registerinhalt einfach als etwas anderes interpretiert, als es ursprünglich gemeint war.

              Funktioniert aber nur, wenn man hardwarenah programmieren kann. Mit Javascript kann man das nicht, weil es keinen direkten Speicherzugriff gibt.

              Man muss sich eine Funktion schreiben, die die Umrechnung von Integer in IEEE-Float manuell vornimmt. Und das dürfte etwas komplizierter werden.

              Ja, zumal man auf diese Weise nur "korrekte" Werte gemäß IEEE 754 hinbekommt. Erhält man vom Remote-System aber fehlerhafte oder denormalisierte Werte, kann man sie nicht exakt rekonstruieren, man erhielte bestenfalls die gleichwertige normalisierte Darstellung oder NaN. Die Sonderfälle +INF und -INF kann man dagegen gezielt "herstellen", indem man einfach die entsprechenden Konstanten des Number-Objekts liest.

              Ähm, hä? Der Hardware-Trick ist, 32 Bits als Integer in den Speicher zu schieben und als Float wieder zu lesen - ohne sie zu verändern.

              Das muss man auch emulieren können. Aufgabe: Was "bedeuten" die folgenden 32 Bits Integer, wenn man sie als IEEE-Float ansehen würde. Wenn die SPS-Hardware fehlerhafte Floats rüberschiebt, hat man ein Problem.

              - Sven Rautenberg

              1. Hallo Sven,

                Ich würde es nicht als Hacker-Trick bezeichnen, sondern eher als die natürliche Methode, wenn man einen Speicher- oder Registerinhalt einfach als etwas anderes interpretiert, als es ursprünglich gemeint war.
                Funktioniert aber nur, wenn man hardwarenah programmieren kann. Mit Javascript kann man das nicht, weil es keinen direkten Speicherzugriff gibt.

                ja, genau.

                Man muss sich eine Funktion schreiben, die die Umrechnung von Integer in IEEE-Float manuell vornimmt. Und das dürfte etwas komplizierter werden.
                Ja, zumal man auf diese Weise nur "korrekte" Werte gemäß IEEE 754 hinbekommt. Erhält man vom Remote-System aber fehlerhafte oder denormalisierte Werte, kann man sie nicht exakt rekonstruieren, man erhielte bestenfalls die gleichwertige normalisierte Darstellung oder NaN. Die Sonderfälle +INF und -INF kann man dagegen gezielt "herstellen", indem man einfach die entsprechenden Konstanten des Number-Objekts liest.
                Ähm, hä? Der Hardware-Trick ist, 32 Bits als Integer in den Speicher zu schieben und als Float wieder zu lesen - ohne sie zu verändern.

                Aber dass der in Javascript nicht zur Verfügung steht, hatten wir ja schon festgestellt. Eine Umwandlung kann also nur so erfolgen, dass man die einzelnen Bits der Integer-Quelle maskiert, bewertet und daraus "von Hand" den Fließkommawert interpretiert.

                Wie IEEE Floating Point aufgebaut ist, dürfte ja allgemein bekannt sein. Der folgende Ansatz, der aus einem 32bit-Integer den entsprechenden 32bit-Float berechnet, könnte ein Start sein. Sonderfälle des Float-Formats wie -0 oder denormalisierte Darstellung berücksichtigt er allerdings nicht, das Ergebnis ist grundsätzlich normalisiert und 0 hat ein positives Vorzeichen.

                function dword2float(dw)  
                 { var s =  dw & 0x80000000;                 // sign: 0=positive  
                   var e = (dw & 0x7F800000) >> 23;          // exponent  
                   var m = (dw & 0x007FFFFF | 0x00800000);   // mantissa  
                   var f;                                    // float result  
                  
                   if (e==0x00)                              // special: zero  
                    { return (0.0);                          // deliberately ignore denormalized numbers  
                    }  
                  
                   if (e==0xFF)                              // special: ±INF or NaN  
                    { if (m)                                 // is mantissa non-zero? indicates NaN  
                         return (Number.NaN);  
                      else                                   // otherwise it's ±INF  
                         return (s ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY);  
                    }  
                  
                   e -= 127;                                 // adjust exponent from offset binary to 2's complement  
                   f = m * pow(2,e-23);                      // compute absolute value of number  
                   return (s ? -f : +f);                     // and return positive or negative depending on sign  
                 }
                

                Wenn die SPS-Hardware fehlerhafte Floats rüberschiebt, hat man ein Problem.

                Das ist genau, was ich im vorigen Posting gesagt habe.

                Ciao,
                 Martin

                --
                Der Stress von heute ist die gute alte Zeit von morgen.
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                1. Ich habe in einem anderen Forum jetzt folgende Funktion bekommen, funktioniert einwandfrei:

                  function back2Real(low, high){
                    var fpnum=low|(high<<16)
                    var negative=(fpnum>>31)&1;
                    var exponent=(fpnum>>23)&0xFF
                    var mantissa=(fpnum&0x7FFFFF)
                    if(exponent==255){
                     if(mantissa!=0)return Number.NaN;
                     return (negative) ? Number.NEGATIVE_INFINITY :
                           Number.POSITIVE_INFINITY;
                    }
                    if(exponent==0)exponent++;
                    else mantissa|=0x800000;
                    exponent-=127
                    var ret=(mantissa*1.0/0x800000)*Math.pow(2,exponent)
                    if(negative)ret=-ret;
                    return ret;
                  }