confusing >> results

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • yawnmoth

    confusing >> results

    Using >> normally shifts bits to the right x number of times, where x
    is specified by the programmer. As an example, 0x40000000 >> 8 yields
    0x00400000. This makes me wonder... why doesn't the same thing happen
    with 0x80000000 >> 8? The number it yields is 0xff800000 - not
    0x00800000. The following script better demonstrates this:

    <?
    echo sprintf('%08x', 0x40000000 >> 8)."\n";
    echo sprintf('%08x', 0x80000000 >> 8);
    ?>

    Anyway, any ideas?

  • Palle Hansen

    #2
    Re: confusing &gt;&gt; results

    yawnmoth wrote:[color=blue]
    > Using >> normally shifts bits to the right x number of times, where x
    > is specified by the programmer. As an example, 0x40000000 >> 8 yields
    > 0x00400000. This makes me wonder... why doesn't the same thing happen
    > with 0x80000000 >> 8? The number it yields is 0xff800000 - not
    > 0x00800000. The following script better demonstrates this:
    >
    > <?
    > echo sprintf('%08x', 0x40000000 >> 8)."\n";
    > echo sprintf('%08x', 0x80000000 >> 8);
    > ?>
    >
    > Anyway, any ideas?[/color]

    My guess is that PHP sees 0x8000000 as a *signed* integer

    Comment

    • Pedro Graca

      #3
      Re: confusing &gt;&gt; results

      Palle Hansen wrote:[color=blue]
      > yawnmoth wrote:[color=green]
      >> Using >> normally shifts bits to the right x number of times, where x
      >> is specified by the programmer. As an example, 0x40000000 >> 8 yields
      >> 0x00400000. This makes me wonder... why doesn't the same thing happen
      >> with 0x80000000 >> 8? The number it yields is 0xff800000 - not
      >> 0x00800000. The following script better demonstrates this:
      >>
      >> <?
      >> echo sprintf('%08x', 0x40000000 >> 8)."\n";
      >> echo sprintf('%08x', 0x80000000 >> 8);
      >> ?>
      >>
      >> Anyway, any ideas?[/color]
      >
      > My guess is that PHP sees 0x8000000 as a *signed* integer[/color]

      Seems like you're right, Palle.

      I tested with this code:

      <?php
      header('Content-Type: text/plain');

      $t = 0x80000000;
      echo $t-1, '; ', $t, '; ', $t + 1, "\n";
      var_dump($t);

      /*********
      * <quote src="http://www.php.net/unpack">
      * CAUTION
      * Note that PHP internally stores integral values as signed. If
      * you unpack a large unsigned long and it is of the same size as
      * PHP internally stored values the result will be a negative
      * number even though unsigned unpacking was specified.
      * </quote>
      *********/

      /* N: unsigned long (always 32 bit, big endian byte order) */
      $unsignedlong = unpack('N', "\x80\x00\x00\x 00");
      var_dump($unsig nedlong);
      ?>


      --
      Mail to my "From:" address is readable by all at http://www.dodgeit.com/
      == ** ## !! ------------------------------------------------ !! ## ** ==
      TEXT-ONLY mail to the whole "Reply-To:" address ("My Name" <my@address>)
      may bypass my spam filter. If it does, I may reply from another address!

      Comment

      • yawnmoth

        #4
        Re: confusing &gt;&gt; results


        Palle Hansen wrote:[color=blue]
        > yawnmoth wrote:[color=green]
        > > Using >> normally shifts bits to the right x number of times, where x
        > > is specified by the programmer. As an example, 0x40000000 >> 8 yields
        > > 0x00400000. This makes me wonder... why doesn't the same thing happen
        > > with 0x80000000 >> 8? The number it yields is 0xff800000 - not
        > > 0x00800000. The following script better demonstrates this:
        > >
        > > <?
        > > echo sprintf('%08x', 0x40000000 >> 8)."\n";
        > > echo sprintf('%08x', 0x80000000 >> 8);
        > > ?>
        > >
        > > Anyway, any ideas?[/color]
        >
        > My guess is that PHP sees 0x8000000 as a *signed* integer[/color]

        Why should >> even be concerned with whether or not integers are signed?

        Comment

        • Chung Leong

          #5
          Re: confusing &gt;&gt; results

          Palle Hansen wrote:[color=blue]
          > yawnmoth wrote:[color=green]
          > > Using >> normally shifts bits to the right x number of times, where x
          > > is specified by the programmer. As an example, 0x40000000 >> 8 yields
          > > 0x00400000. This makes me wonder... why doesn't the same thing happen
          > > with 0x80000000 >> 8? The number it yields is 0xff800000 - not
          > > 0x00800000. The following script better demonstrates this:
          > >
          > > <?
          > > echo sprintf('%08x', 0x40000000 >> 8)."\n";
          > > echo sprintf('%08x', 0x80000000 >> 8);
          > > ?>
          > >
          > > Anyway, any ideas?[/color]
          >
          > My guess is that PHP sees 0x8000000 as a *signed* integer[/color]

          No, PHP sees 0x80000000 as a double, because the number is beyond the
          range of an integer (on 32 bit systems).

          Comment

          • Jerry Stuckle

            #6
            Re: confusing &gt;&gt; results

            Chung Leong wrote:[color=blue]
            > Palle Hansen wrote:
            >[color=green]
            >>yawnmoth wrote:
            >>[color=darkred]
            >>>Using >> normally shifts bits to the right x number of times, where x
            >>>is specified by the programmer. As an example, 0x40000000 >> 8 yields
            >>>0x00400000 . This makes me wonder... why doesn't the same thing happen
            >>>with 0x80000000 >> 8? The number it yields is 0xff800000 - not
            >>>0x00800000 . The following script better demonstrates this:
            >>>
            >>><?
            >>>echo sprintf('%08x', 0x40000000 >> 8)."\n";
            >>>echo sprintf('%08x', 0x80000000 >> 8);
            >>>?>
            >>>
            >>>Anyway, any ideas?[/color]
            >>
            >>My guess is that PHP sees 0x8000000 as a *signed* integer[/color]
            >
            >
            > No, PHP sees 0x80000000 as a double, because the number is beyond the
            > range of an integer (on 32 bit systems).
            >[/color]

            No, 0x80000000 is exactly 32 bits and is taken as a signed integer.

            --
            =============== ===
            Remove the "x" from my email address
            Jerry Stuckle
            JDS Computer Training Corp.
            jstucklex@attgl obal.net
            =============== ===

            Comment

            • Jerry Stuckle

              #7
              Re: confusing &gt;&gt; results

              yawnmoth wrote:[color=blue]
              > Palle Hansen wrote:
              >[color=green]
              >>yawnmoth wrote:
              >>[color=darkred]
              >>>Using >> normally shifts bits to the right x number of times, where x
              >>>is specified by the programmer. As an example, 0x40000000 >> 8 yields
              >>>0x00400000 . This makes me wonder... why doesn't the same thing happen
              >>>with 0x80000000 >> 8? The number it yields is 0xff800000 - not
              >>>0x00800000 . The following script better demonstrates this:
              >>>
              >>><?
              >>>echo sprintf('%08x', 0x40000000 >> 8)."\n";
              >>>echo sprintf('%08x', 0x80000000 >> 8);
              >>>?>
              >>>
              >>>Anyway, any ideas?[/color]
              >>
              >>My guess is that PHP sees 0x8000000 as a *signed* integer[/color]
              >
              >
              > Why should >> even be concerned with whether or not integers are signed?
              >[/color]

              Well, it's got to make a decision one way or the other. As a signed
              integer, 0x80000000 is -2,147,483,648. Shift right one bit and you get
              0xc0000000, which is 1,073,741,824 - the correct result for dividing by 2.



              --
              =============== ===
              Remove the "x" from my email address
              Jerry Stuckle
              JDS Computer Training Corp.
              jstucklex@attgl obal.net
              =============== ===

              Comment

              • Pedro Graca

                #8
                Re: confusing &gt;&gt; results

                Chung Leong wrote:[color=blue]
                > Palle Hansen wrote:[color=green]
                >> yawnmoth wrote:[color=darkred]
                >> > <?
                >> > echo sprintf('%08x', 0x40000000 >> 8)."\n";
                >> > echo sprintf('%08x', 0x80000000 >> 8);
                >> > ?>[/color][/color][/color]
                [color=blue][color=green]
                >> My guess is that PHP sees 0x8000000 as a *signed* integer[/color][/color]
                [color=blue]
                > No, PHP sees 0x80000000 as a double, because the number is beyond the
                > range of an integer (on 32 bit systems).[/color]

                Right, but the >> operator "casts" the float to an int.

                ~$ php -r '$x = 0x80000000; var_dump($x);'
                float(214748364 8)

                ~$ php -r '$x = 0x80000000 >> 0; var_dump($x);'
                int(-2147483648)

                --
                If you're posting through Google read <http://cfaj.freeshell. org/google>

                Comment

                • Pedro Graca

                  #9
                  Re: confusing &gt;&gt; results

                  yawnmoth wrote:[color=blue]
                  > Why should >> even be concerned with whether or not integers are signed?[/color]

                  ~$ php -r 'echo -2 << 2, "\n";'
                  -8
                  ~$ php -r 'echo -8 >> 2, "\n";'
                  -2

                  --
                  If you're posting through Google read <http://cfaj.freeshell. org/google>

                  Comment

                  • Pedro Graca

                    #10
                    Re: confusing &gt;&gt; results

                    Pedro Graca wrote:[color=blue]
                    > yawnmoth wrote:[color=green]
                    >> Why should >> even be concerned with whether or not integers are signed?[/color]
                    >
                    > ~$ php -r 'echo -8 >> 2, "\n";'[/color]

                    I forgot the rest of the post ...

                    Let's say -8 in binary is (ignore the spaces)
                    MSB == 10000000 00000000 00000000 00001000 == LSB

                    if you shift this right without concern for the sign, you get
                    MSB == 00100000 00000000 00000000 00000010 == LSB

                    which is 536870914


                    Do you think -8 >> 2 (-8 divided by 4) should equal 536870914? :)

                    --
                    If you're posting through Google read <http://cfaj.freeshell. org/google>

                    Comment

                    • Jerry Stuckle

                      #11
                      Re: confusing &gt;&gt; results

                      Pedro Graca wrote:[color=blue]
                      > Pedro Graca wrote:
                      >[color=green]
                      >>yawnmoth wrote:
                      >>[color=darkred]
                      >>>Why should >> even be concerned with whether or not integers are signed?[/color]
                      >>
                      >>~$ php -r 'echo -8 >> 2, "\n";'[/color]
                      >
                      >
                      > I forgot the rest of the post ...
                      >
                      > Let's say -8 in binary is (ignore the spaces)
                      > MSB == 10000000 00000000 00000000 00001000 == LSB
                      >
                      > if you shift this right without concern for the sign, you get
                      > MSB == 00100000 00000000 00000000 00000010 == LSB
                      >
                      > which is 536870914
                      >
                      >
                      > Do you think -8 >> 2 (-8 divided by 4) should equal 536870914? :)
                      >[/color]

                      But -8 binary is:

                      11111111 11111111 11111111 11111000

                      --
                      =============== ===
                      Remove the "x" from my email address
                      Jerry Stuckle
                      JDS Computer Training Corp.
                      jstucklex@attgl obal.net
                      =============== ===

                      Comment

                      • Pedro Graca

                        #12
                        Re: confusing &gt;&gt; results

                        Jerry Stuckle wrote:[color=blue]
                        > Pedro Graca wrote:[color=green]
                        >>
                        >> Let's say -8 in binary is (ignore the spaces)
                        >> MSB == 10000000 00000000 00000000 00001000 == LSB
                        >>
                        >> if you shift this right without concern for the sign, you get
                        >> MSB == 00100000 00000000 00000000 00000010 == LSB
                        >>
                        >> which is 536870914
                        >>
                        >>
                        >> Do you think -8 >> 2 (-8 divided by 4) should equal 536870914? :)
                        >>[/color]
                        >
                        > But -8 binary is:
                        >
                        > 11111111 11111111 11111111 11111000[/color]

                        Indeed it is (on my machines).
                        However some other machine running PHP could use sign-and-magnitude
                        representation of negative numbers instead of two's complement.
                        For that machine my reasoning above stands :-)

                        My book on C (The C Programming Language, Kernighan & Ritchie) says this
                        about >>

                        <quote>
                        Right shifting a signed quantity will fill with sign bits
                        ("arithmetic shift") on some machines and with 0-bits
                        ("logical shift") on others.
                        </quote>

                        So, taking into account that PHP is written in C, I guess the effect of
                        0x80000000 >> 8
                        is implementation defined (can be 0xff800000 on some (most) machines
                        and 0x00800000 on other machines)

                        And as PHP does not have C's `unsigned long int` it's best to avoid
                        right shifting negative values.

                        --
                        If you're posting through Google read <http://cfaj.freeshell. org/google>

                        Comment

                        • Jerry Stuckle

                          #13
                          Re: confusing &gt;&gt; results

                          Pedro Graca wrote:[color=blue]
                          > Jerry Stuckle wrote:
                          >[color=green]
                          >>Pedro Graca wrote:
                          >>[color=darkred]
                          >>>Let's say -8 in binary is (ignore the spaces)
                          >>>MSB == 10000000 00000000 00000000 00001000 == LSB
                          >>>
                          >>>if you shift this right without concern for the sign, you get
                          >>>MSB == 00100000 00000000 00000000 00000010 == LSB
                          >>>
                          >>>which is 536870914
                          >>>
                          >>>
                          >>>Do you think -8 >> 2 (-8 divided by 4) should equal 536870914? :)
                          >>>[/color]
                          >>
                          >>But -8 binary is:
                          >>
                          >> 11111111 11111111 11111111 11111000[/color]
                          >
                          >
                          > Indeed it is (on my machines).
                          > However some other machine running PHP could use sign-and-magnitude
                          > representation of negative numbers instead of two's complement.
                          > For that machine my reasoning above stands :-)
                          >
                          > My book on C (The C Programming Language, Kernighan & Ritchie) says this
                          > about >>
                          >
                          > <quote>
                          > Right shifting a signed quantity will fill with sign bits
                          > ("arithmetic shift") on some machines and with 0-bits
                          > ("logical shift") on others.
                          > </quote>
                          >
                          > So, taking into account that PHP is written in C, I guess the effect of
                          > 0x80000000 >> 8
                          > is implementation defined (can be 0xff800000 on some (most) machines
                          > and 0x00800000 on other machines)
                          >
                          > And as PHP does not have C's `unsigned long int` it's best to avoid
                          > right shifting negative values.
                          >[/color]

                          Pedro,

                          Just because it's undefined in C doesn't mean it has to be in PHP.
                          Different languages can have different rules.

                          And everything is eventually built on machine language anyway.

                          --
                          =============== ===
                          Remove the "x" from my email address
                          Jerry Stuckle
                          JDS Computer Training Corp.
                          jstucklex@attgl obal.net
                          =============== ===

                          Comment

                          Working...