Inching Along Through PHP

24 12 2013

Geometer Moth, Geometridae

Geometer Moth, Geometridae (Photo credit: Andreas Kay)

It begins its life journey first as larva.  Later, a metamorphosis occurs, causing  it to re-emerge as the exquisite flying creature featured above.  Perhaps you may have seen the movie  clip in which Danny Kaye sings about it in a song whose poignant lyrics caution us to not fixate on measuring nature  or we risk failing to appreciate its beauty. I refer to the inchworm, the colloquial name for the tilde character which  represents the bitwise NOT operator in several programming languages, including PHP.

A chance tweet  between Nikita Popov and Phil Sturgeon steered me to  read about Secret Perl Operators, causing me to ponder PHP’s own inchworm.

The following example illustrates the basic usage of the “~”, a unary operator:

$x = 2;
echo ~$x; // -3

What happens on modern computers which use 2s Complement processing is that all the bits of the integer are inverted, i.e. zeros become ones while ones change into zeros.  Then, the value one is added to the result.  This process happens regardless of the size of the integer.  Thus, if you had a 4-bit integer, the binary bit pattern for 2 renders as follows :

0010

Applying the 2s Complement method to initially produces the following change:

1101

Next, 2s Complement method finishes by adding the value one which produces the following binary number:

1110

Since the left-most bit is ON, its numerical value is -8 which when added to 4 and then 2 results in -2.   The bitwise NOT operator requires one more action to complete its task, namely the subtraction of the value one from the preceding number, as follows:

 1110
-   1
------
 1101

Expressed in decimal notation:  -2 – 1 =  -3

Depite being unary in nature, the PHP’s bitwise NOT, like that of C, Perl and Ruby, may combine with the unary minus operator, giving rise to what has been dubbed “inchworm-on-a-stick.” Click any of the following links to see examples in the following respective languages: C, Perl and Ruby.

The inchworm-on-a-stick was first discovered in Perl by Ton Hospel back in 2002 according to Philippe Bruhat in a fascinating piece at http://search.cpan.org/~book/perlsecret-1.004/lib/perlsecret.pod#Inchworm_on_a_stick__~-__and__-~.

What makes the  ‘~-‘ sequence of symbols noteworthy is that together they combine to effectively decrement a number just as if you had actually applied the more usual operator consisting of two minus signs –, as you may note:

$x = 100;
echo ~-$x; // 99

The inchworm-on-a- stick is certainly prettier than PHP’s normal “–” operator.  But, is this ability an example of PHP allowing developers to do something that is completely unnecessary? Let’s examine the opcodes, available at http://3v4l.org/WsfXe/vld#tabs, and  total five, among which figure SUB and BW_NOT. The order  of their arrangement indicates that subtraction occurs before the bitwise NOT takes effect.

What is particularly striking with reference to the two opcodes is that the 2s Complement method will trigger  twice, once for conversion of 100 to -100 (actual code is 0 – 100 since unary minus despite its name in PHP requires two operands, the first being zero which will subtract the specified number from it).  After the unary minus operation completes, then the bitwise NOT takes over, applying the 2s Complement method again before finally subtracting the value one from the result.  All of this effort seems like a silly waste of time when one could more efficiently achieve the desired outcome of decreasing 100 with the usual PHP operator, as follows:

$x = 100;
echo --$x; // 99

Using the inch-worm-on-a-stick, if for some reason you wished to write obfuscated code, the following is certainly feasible:

const TIMES = 4;
for ($i=TIMES, $x = ~-1; $i > $x; $i--) {
  echo $i,"\n";
}

If you now think that the inch-worm-on-a-stick is unnecessary for PHP, consider the following code:

$x = 8;
$y1 = ~-$x * 4;
$y2 = ($x-1) * 4;
var_dump($y1,$y2) ; //28,28

In this snippet, the inchworm-on-a-stick trick saves you from having to use parentheses and explicitly subtract one.

Although the inchworm is apparently broken in Perl  (see http://www.nntp.perl.org/group/perl.fwp/2012/03/msg4175.html)  since it reputedly fails to decrement numbers less than zero and only increments negative numbers, I’m happy to report that PHP doesn’t seem to share these problems.  Note the following:

$x = -8;
$y1 = ~-$x * 4;
$y2 = ($x - 1) * 4;
var_dump($y1,$y2) ; //-36, -36

You may also reverse the sequence of operators to increment using “-~”, as follows:

$x = 8;
$y1 = -~$x * 4;
$y2 = ($x + 1) * 4;
var_dump($y1,$y2); //36,36

This trick, too, saves you from having to use parentheses as well as  specifying the addition of one. Note these inchworm-on-a-stick tricks only work correctly in versions PHP5.2.3 – PHP5.5.7.

This work is licensed under a Creative Commons License

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: