hotti: Bitoperatoren und Unsigned Integer

hi,

hat jemand eine Idee, wie ich JavaScript dazu bringen kann, dass Bitoperatoren nicht den +- Integerbereich ausschöpfen, sondern sozusagen strict unsigned operieren?

Falls es da was gibt, was nur in neuen Browsern geht, wäre ok.

Horst Rathloos

  1. Hallo,

    hat jemand eine Idee, wie ich JavaScript dazu bringen kann, dass Bitoperatoren nicht den +- Integerbereich ausschöpfen, sondern sozusagen strict unsigned operieren?

    nein, die Frage ergibt schon keinen Sinn.
    Bitweise logische Operationen kennen so etwas wie ein Vorzeichen prinzipiell nicht. Das gibt es nur, wenn die Operanden in irgendeinem Kontext wieder als Integerzahlen interpretiert werden.

    var a = 433;    // positive Integerzahl  
    var b =  -2;    // negative Integerzahl  
      
    alert (a & b);  // ergibt 432
    

    Betrachte also die bitweise-logischen Operationen losgelöst von so etwas wie einem Vorzeichen.

    Aber wie kommst du überhaupt auf die Frage? Worin besteht das konkrete Problem?

    Ciao,
     Martin

    --
    Krankenschwester zum fassungslosen Vater von Drillingen: Nein, Sie sollen sich keins aussuchen! Alle drei sind Ihre!
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. hi,

      Aber wie kommst du überhaupt auf die Frage? Worin besteht das konkrete Problem?

      alert( inet_aton('192.168.2.1') |~ inet_aton('255.255.255.0') );

      ergibt einen negativen Integer. Das Ergebnis ist in diesem Fall richtig.
      Anders jedoch hier:

        
      // maskenlänge zu einer uint 32 bit Zahl umrechnen  
      // masklen 0..32 !!!  
      int masklen_to_num(int masklen){  
          if(masklen == 0) return 0;  
          else return(0xffffFFFF <<(32 - masklen));  
      }  
      
      

      Diese c-Funktion, den shift-Op anwendend, funktioniert nicht mit JavaScript, weil infolge shift die Zahlen negativ werden.
      Möglicherweise gibt es für die modernen Browser ein Pragma oder die Möglichkeit einen Cast-Operator anzuwenden?

      Horst (geht erneut auf die Suche)

      1. Hallo hotti,

        das Vorzeichen einer Integerzahl ist reine Interpretation. Binär sind +255 und -128 identisch (FF). Wenn du nach Bit-Operationen ein Vorzeichenproblem hast, weil Javascript keine Datentypen kennt und die Daten "nach bestem Wissen und Gewissen" interpretiert, musst du das selbst geradebiegen. Vielleicht hilft ein Verunden mit FF.

        Gruß, Jürgen

        1. Hi Jürgen,

          das Vorzeichen einer Integerzahl ist reine Interpretation. Binär sind +255 und -128 identisch (FF). Wenn du nach Bit-Operationen ein Vorzeichenproblem hast, weil Javascript keine Datentypen kennt und die Daten "nach bestem Wissen und Gewissen" interpretiert, musst du das selbst geradebiegen.

          Ja, Du hast Recht ;)

          Meine Lösung ist nun: Anwenden eines Typed Arrays und DataView. Entsprechende Methoden erzwingen Unsigned.

            
          function masklen_to_num(masklen){  
              if(masklen == 0){  
                  return 0;  
              }  
              else{  
                  var buffer = new ArrayBuffer(4);  
                  var dv = new DataView(buffer);  
                  dv.setUint32(0, (0xffffFFFF <<(32 - masklen)));  
                  var num = dv.getUint32(0);  
                  return num;  
              }  
          }  
          
          

          HTML5 rockt, ich bin begeistert!!!

  2. Meine Herren!

    hat jemand eine Idee, wie ich JavaScript dazu bringen kann, dass Bitoperatoren nicht den +- Integerbereich ausschöpfen, sondern sozusagen strict unsigned operieren?

    Numerische Werte in JavaScript werden als Double Precision Floating Point (64bit) nach IEEE 754 gespeichert.

    Das heißt insbesondere, dass die Bits verschiedene Bedeutungen haben (Vorzeichen, Basis, Exponent, Mantisse). Binär-Operationen sind also höchst kritisch zu beäugen.

    --
    “All right, then, I'll go to hell.”
    1. Hallo,

      Numerische Werte in JavaScript werden als Double Precision Floating Point (64bit) nach IEEE 754 gespeichert.

      grundsätzlich, also auch wenn sie in den Wertebereich von 32bit-Integers passen würden?
      Aber unabhängig davon sind Bitweise-logische Operationen nur für Integerwerte definiert, bei Operatoren wie & oder | werden die Operanden also ohnehin in Integer gewandelt.

      Das heißt insbesondere, dass die Bits verschiedene Bedeutungen haben (Vorzeichen, Basis, Exponent, Mantisse). Binär-Operationen sind also höchst kritisch zu beäugen.

      Das gilt aber nur, wenn man es schafft, die automatische Typanpassung von Javascript zu umgehen.

      So  long,
       Martin

      --
      F: Was ist schlimmer: Alzheimer oder Parkinson?
      A: Parkinson. Lieber mal ein Bier vergessen zu zahlen, als eins verschütten.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    2. hi,

      Das heißt insbesondere, dass die Bits verschiedene Bedeutungen haben (Vorzeichen, Basis, Exponent, Mantisse). Binär-Operationen sind also höchst kritisch zu beäugen.

      So isses. Die Lösung habe ich ja schon beschrieben: Es muss dafür gesorgt werden, dass Bit-Operationen, 32 Bit, IPv4 betreffend, in einem eigens dafür definierten Puffer mit genau 32 Bit erfolgen. Mit modernen Browsern, die DataView und ArrayBuffer können, ist das nun möglich (siehe meinen CIDR-Calculator, komplett in JavaScript).

      MfG

  3. Hi,

    hat jemand eine Idee, wie ich JavaScript dazu bringen kann, dass Bitoperatoren nicht den +- Integerbereich ausschöpfen, sondern sozusagen strict unsigned operieren?

    hmm ... strict unsigned habe ich noch nicht gesehen, aber ich glaube ein

    var num = ...;
    (num << 0) // cast

    erzeugt eine 32 Bit Zahl. Kenne aber die Specs nicht genau, hab's nur hier und da mal gesehen.

    1. hi,

      hmm ... strict unsigned habe ich noch nicht gesehen, aber ich glaube ein

      var num = ...;
      (num << 0) // cast

      nicht glauben, sondern machen ;)

      erzeugt eine 32 Bit Zahl. Kenne aber die Specs nicht genau, hab's nur hier und da mal gesehen.

      _('mesg').innerHTML = 0xFFFFffff << 0; // -1

      Das ist also völlig unbrauchbar, was da ausgegeben wird. Das liegt, wie 1UnitedPower schrieb, an der inneren Verarbeitung der Bytes und die ist, weil 'float 64 bit': eben nicht auf einen uint32 ausgerichtet.

      Mit den neuen Features (MDN, Moz, FF), sprich über ein DataView, erfolgt die Integer-Operation direkt in einem 32-Bit-Puffer:

        
      var buffer = new ArrayBuffer(4); // 4 Bytes  
      var dv = new DataView(buffer);  
      dv.setUint32(0, 0xFFFFffff << 0);  
      var u32 = dv.getUint32(0); // Big Endian  
      _('mesg').innerHTML = u32; // 4294967295  
      
      

      was denn auch das erwartete Ergebnis liefert. Mir ist diese Lösung sofort in den Sinn gekommen, nachdem ich JürgenB's POST gelesen habe. Was Berechnungen zu IP-Adressen v4 betrifft, da habe ich sehr viele JS-Lösungen gesehen (z.B. zur Funktion inet_aton()), wo umständlich über einen float gerechnet und dann auch noch gerundet wird.

      Das ist in etwa so, als würdest Du bei einer Wurzel aus vier einen Bruch bekommen, der zielgerichtet gerundet werden muss, damit ungefähr zwei rauskommt ;)

      Freilich hinkt der Vergleich, aber was das Rechnen mit Uint32 und IPv4 betrift, da werden tatsächlich nur ein paar Bits hin und her geschoben. So habe ich Small Library for IPv4 als eine kleine Library gestern abend mal vervollständigt.

      Viele Grüße.

      1. Meine Herren!

        _('mesg').innerHTML = 0xFFFFffff << 0; // -1

        Das ist also völlig unbrauchbar, was da ausgegeben wird. Das liegt, wie 1UnitedPower schrieb, an der inneren Verarbeitung der Bytes und die ist, weil 'float 64 bit': eben nicht auf einen uint32 ausgerichtet.

        Der Martin hat mich an dieser Stelle ja bereits korrigiert. Hier nochmal eine genauere Erläuterung:

        Alle numerischen Zahlenwerte werden als double-precision 64bit floating point gespeichert. Bestimmte Operatoren, wie die Binär-Operatoren, wandeln die binäre Repräsentation ihrer Operanden allerdings um. Das Ergebnis ist allerdings wieder eine Gleitkommazahl. Der Wertebereich des Ergebnisses liegt aber im Wertebereich des intern benutzten Binärformats.

        Ein Beispiel: Der Linksshift-Operator << rechnet mit einer 32bit-Int Repräsentation des linken und einer 32bit-UInt Repräsentation des rechten Operanden. Der Wertebereich von 32bit-Int reicht von -2^31-1 bis 2^31-1. Insbesondere gehört der Wert 0xFFFFffff also nicht zum Wertebereich. Es ist folglich keine intuitive Umwandlung der Repräsentation möglich. Der Algorithmus, der diese Ausnahme Umwandlung vornimmt kann hier in der Spezifikation nachgelesen werden. Wie hottis Test schon gezeigt hat, wird der Wert auf eine 0 gemappt.

        Interessant für dich hotti ist der vorzeichenlose Rechtsshift-Operator >>>.
        Der rechnet nämlich mit einer 32bit-UInt Repräsentation seines linken Operanden. 0xFFFFffff liegt also im Darstellbaren Wertebereich.

          
        0xFFFFffff >>> 0;  // 4294967295  
        -1 >>> 0;          // 4294967295  
        0x100000000 >>> 0; // 0  
        0x100000001 >>> 0; // 1  
        
        
        --
        “All right, then, I'll go to hell.”
        1. hi,

          Interessant für dich hotti ist der vorzeichenlose Rechtsshift-Operator >>>.

          Ja, der >>> funktioniert erwartungsgemäß. Ist aber letztendlich auch nicht zu gebrauchen, weil die Negation nicht das macht, was sie soll:

          Beispiel Netzmaske, Maskenlänge 16 (255.255.0.0),

          Wir schieben 16 Nullen von links rein und drehen dann alle Bits rum:
          ~(0xFFFFFFFF >>> 16);

          Perl: 4294901760 (as expected)
          JS: -65536

          Besser: (0xFFFFffff << 16) über einen ArrayBuffer, da haben wir die Bits gleich da, wo sie hingehören ;)

          Horst

          1. Meine Herren!

            Wir schieben 16 Nullen von links rein und drehen dann alle Bits rum:
            ~(0xFFFFFFFF >>> 16);

            Perl: 4294901760 (as expected)
            JS: -65536

            Wenn das Ergebnis deines Terms im UInt32 Wertebereich liegen soll, musst du das Ergebnis natürlich auch wieder auf den Bereich mappen:

            ~(0xFFFFFFFF >>> 16) >>> 0; // 4294901760

            --
            “All right, then, I'll go to hell.”
            1. hi,

              Wenn das Ergebnis deines Terms im UInt32 Wertebereich liegen soll, musst du das Ergebnis natürlich auch wieder auf den Bereich mappen:

              ~(0xFFFFFFFF >>> 16) >>> 0; // 4294901760

              Ja klar, danke Dir ;)

              Aber schau mal, mittlerweile gibt es DataView und ArrayBuffer. Vordem wäre ich nie auf die Idee gekommen, einen Subnet-Calculator mit JavaScript zu machen, auch wenn das algebraisch geht; inet_aton(Gelesen als a to n) macht die Sache recht einfach über die Binary, mit dem DataView ists auch möglich, die Byte-Order von Big auf Little Endian umzuschalten, was gelegentlich (CISCO) gewünscht ist.

              Nichtsdestoweniger ist der '>>>' Operator trotzdem eine feine Sache, wenn es um u32 geht.

              Viele Grüße!

          2. Meine Herren!

            Besser: (0xFFFFffff << 16) über einen ArrayBuffer, da haben wir die Bits gleich da, wo sie hingehören ;)

            Besser ist so weitläufiger Begriff. Ich finde deinen Code auch expressiver. Der Unsigned-Rightshift-Operator scheint irgend einen Voodoo zu machen.

            Performanter ist er aber: http://jsperf.com/touint32

            --
            “All right, then, I'll go to hell.”
            1. hi ;

              Besser ist so weitläufiger Begriff. Ich finde deinen Code auch expressiver. Der Unsigned-Rightshift-Operator scheint irgend einen Voodoo zu machen.

              Performanter ist er aber: http://jsperf.com/touint32

              Ok, ipv4 new version, done ;)

              Is sowieso nur Hobby.

              Viele Grüße!

            2. hi,

              cooler Tipp: >>> 0;

                
              function inet_aton(ip){  
                  var a = new Array();  
                  a = ip.split('.');  
                  var ipnum = ((a[0] << 24) >>> 0)  + ((a[1] << 16) >>> 0) + ((a[2] << 8) >>> 0) + (a[3] >>> 0);  
                  return ipnum;  
              }  
              
              

              also, wer, wie auch immer, nicht mit ArrayBuffer oder DataView schaffen möchte ;)

              SCNR: Deviation Pattern: <<<<<<<<<<<...>>>>>>>>>>>...<<<<<<...>>>...

  4. Meine Herren!

    Besser könnte das Timing von Dr. Axel Rauschmayer in diesem Fall nicht sein:
    http://www.2ality.com/2014/02/javascript-integers.html

    Btw. ein sehr lesenswertes Blog, das sich vor allem mit den Feinheiten von JavaScript beschäftigt.

    --
    “All right, then, I'll go to hell.”
    1. Hi,

      danke für Deine Recherche. Andere Frage:
      Gibt es einen standartisierten Codec für Datentypen, also eine Zuordnung von float, double, string, int usw. zu einer Zahl?

      Fiktives Beispiel: 1 => integer, 2 => float, 3 => string usw. mehr als 255 dürften das ja nicht sein, oder?

      Danke im Vorab!

      1. Meine Herren!

        danke für Deine Recherche.

        Nichts zu danken, das wurde mir von meinem Feedreader sozusagen aufgedrängt und ist dann bis hier hin durch gekleckert ;)

        Andere Frage:
        Gibt es einen standartisierten Codec für Datentypen, also eine Zuordnung von float, double, string, int usw. zu einer Zahl?

        Das weiß ich nicht, EcmaScript spezifiziert die internen Algorithmen für die Zuordnung jedenfalls selbst und nimmt dabei AFAIK keinen Bezug auf einen existierenden Standard.

        --
        “All right, then, I'll go to hell.”
        1. Das weiß ich nicht, EcmaScript spezifiziert die internen Algorithmen für die Zuordnung jedenfalls selbst und nimmt dabei AFAIK keinen Bezug auf einen existierenden Standard.

          Da kocht wohl jeder sein eigenes Süppchen, meine Recherchen haben auch nichts ergeben.

      2. Hallo,

        Gibt es einen standartisierten ...

        nein, mit Sicherheit nicht. Aber vielleicht einen standar_d_isierten.

        Ciao,
         Martin

        --
        Lieber mit Betty im Wald
        als mit Waldi im Bett.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Om nah hoo pez nyeetz, Der Martin!

          Gibt es einen standartisierten ...
          nein, mit Sicherheit nicht. Aber vielleicht einen standar_d_isierten.

          Wobei ich den Fehler im Gegensatz zu Standard - Standart noch nachvollziehen kann, denn man spricht es ja tatsächlich mit „t“.

          https://de.wiktionary.org/wiki/Standardisierung

          und obwohl wiktionary auch für Standard das t in der Lautschrift hat, bemühe ich mich, dieses t wesentlich weicher zu sprechen.

          Matthias

          --
          Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Plane und Planeten.

          1. Hallo,

            Gibt es einen standartisierten ...
            nein, mit Sicherheit nicht. Aber vielleicht einen standar_d_isierten.
            Wobei ich den Fehler im Gegensatz zu Standard - Standart noch nachvollziehen kann, denn man spricht es ja tatsächlich mit „t“.

            was, "standardisieren"? Nein. Schon immer mit einem weichen 'd'. Und "Standard" natürlich auch mit einem weichen, fast stummen 'd' am Ende, aber keinesfalls mit einem harten 't'.

            https://de.wiktionary.org/wiki/Standardisierung
            und obwohl wiktionary auch für Standard das t in der Lautschrift hat, ...

            Hmm. Meines Erachtens falsch.

            bemühe ich mich, dieses t wesentlich weicher zu sprechen.

            Yo, ich wäre nie auf die Idee gekommen, das 'd' in der Wortmitte hart auszusprechen. Im Auslaut, meinetwegen, das tun viele Leute (auch bei anderen Wörtern und Buchstaben, etwa Bund, Feld, Korb, halb).
            Eine ähnliche Eigentümlichkeit hört man gelegentlich bei 'ng' am Wortende: Das sprechen manche Leute so aus, als wäre ein 'k' am Schluss (z.B. bei Gesang, Ding, allgemein die Endung -ung). Das läuft mir dann auch immer kalt den Rücken runter.

            Ciao,
             Martin

            --
            Liebet eure Feinde - vielleicht schadet das ihrem Ruf.
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. @@Der Martin:

              nuqneH

              Und "Standard" natürlich auch mit einem weichen, fast stummen 'd' am Ende

              Es gibt kein stimmloses d; das wäre [t]. Es gibt verschieden stake Aspiration: [t] vs. [tʰ].

              Hatten wir doch schonmal: http://forum.de.selfhtml.org/archiv/2010/8/t199809/#m1345579 ff.

              Eine ähnliche Eigentümlichkeit hört man gelegentlich bei 'ng' am Wortende: Das sprechen manche Leute so aus, als wäre ein 'k' am Schluss (z.B. bei Gesang, Ding, allgemein die Endung -ung). Das läuft mir dann auch immer kalt den Rücken runter.

              Bei „Gesang“ und „Ding“ würde ich das nicht tun; bei „Endung“ schon eher.

              Und bei „Hals“ könnte es am Ende auch wie [ts] klingen, so wie bei „halt’s“ und „Salz“.

              Qapla'

              --
              „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
              1. Hi,

                Und "Standard" natürlich auch mit einem weichen, fast stummen 'd' am Ende
                Es gibt kein stimmloses d; das wäre [t]. Es gibt verschieden stake Aspiration: [t] vs. [tʰ].

                ich hab auch nichts von "stimmlos" geschrieben.

                Hatten wir doch schonmal: http://forum.de.selfhtml.org/archiv/2010/8/t199809/#m1345579 ff.

                Stimmt, ich erinnere mich. Und vertrete immer noch denselben Standpunkt.

                Eine ähnliche Eigentümlichkeit hört man gelegentlich bei 'ng' am Wortende: Das sprechen manche Leute so aus, als wäre ein 'k' am Schluss (z.B. bei Gesang, Ding, allgemein die Endung -ung). Das läuft mir dann auch immer kalt den Rücken runter.
                Bei „Gesang“ und „Ding“ würde ich das nicht tun; bei „Endung“ schon eher.

                Bei -ung tut meine Mutter das auch häufig. Klingt für mich trotzdem irgendwie falsch.

                Und bei „Hals“ könnte es am Ende auch wie [ts] klingen, so wie bei „halt’s“ und „Salz“.

                Autschn.

                Ciao,
                 Martin

                --
                Die letzten Worte des Systemadministrators:
                Nur gut, dass ich ein intaktes Backup habe.
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                1. @@Der Martin:

                  nuqneH

                  Und bei „Hals“ könnte es am Ende auch wie [ts] klingen, so wie bei „halt’s“ und „Salz“.

                  Autschn.

                  „Hals Maul!“ —Freddy Farzadi, Video ab 7:15 – und danach ab 0:00 ;-)

                  Qapla'

                  --
                  „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
        2. hi,

          Gibt es einen standartisierten ...

          nein, mit Sicherheit nicht. Aber vielleicht einen standar_d_isierten.

          Das hat mich bei der letzten Gradwanderung auch etwas irritiert ;)

          Vielleich gibts ja auch einen Unterschied zwischen Grat und Krumm.

          SCNR;

          1. Meine Herren!

            Das hat mich bei der letzten Gradwanderung auch etwas irritiert ;)

            Ich war bis jetzt tatsächlich der Überzeugung Grat schriebe sich mit „d“, eben wie die Maßeinheit oder der Dienstgrad. Danke für die Korrektur.

            --
            “All right, then, I'll go to hell.”
            1. Aber mein Herr!

              Das hat mich bei der letzten Gradwanderung auch etwas irritiert ;)

              Ich war bis jetzt tatsächlich der Überzeugung Grat schriebe sich mit „d“, eben wie die Maßeinheit oder der Dienstgrad. Danke für die Korrektur.

              Und ich danke Dir: Schönes Beispiel für einen klassischen systematischen Fehler ;)

              $SMTP <=> $SNMP;

            2. Om nah hoo pez nyeetz, 1UnitedPower!

              Ich war bis jetzt tatsächlich der Überzeugung Grat schriebe sich mit „d“, eben wie die Maßeinheit oder der Dienstgrad. Danke für die Korrektur.

              Wobei man doch bei einer Gratwanderung völlig gratis abstürzen kann.

              Matthias

              --
              Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Git und Gitarre.

          2. Hallo,

            Gibt es einen standartisierten ...
            nein, mit Sicherheit nicht. Aber vielleicht einen standar_d_isierten.
            Das hat mich bei der letzten Gradwanderung auch etwas irritiert ;)

            ich erinnere mich an diese Stelle. Da habe ich mir einen Kommentar mit Mühe verkniffen.

            Vielleich gibts ja auch einen Unterschied zwischen Grat und Krumm.

            Bestimmt. Oder zwischen Grat und Kelvin. :-)

            Ciao,
             Martin

            --
            Bitte komme jemand mit einem *g* zum Wochenende, damit nicht über mich gelacht wird.
              (Gunnar Bittersmann)
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Hallo,

              Bestimmt. Oder zwischen Grat und Kelvin. :-)

              Der Unterschied zwischen Grat und Kelvin ist größer als der zwischen Java und Javascript.

              Gruß
              Kalk

              1. Der Unterschied zwischen Grat und Kelvin ist größer als der zwischen Java und Javascript.

                Selbst mit d.

                Der Unterschied zwischen Grad und Kelvin ist ungefähr der wie zwischen Java und Script.