X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlfaq4.pod;h=faccc22d293b374c20382a945656a593f51ae219;hb=17c338f39c13131c1bc175ef38013b54bc98396d;hp=72eb8d8dee6ce50ce811437e8a3e7f3648dedaf0;hpb=24f1ba9b2223fc835b4bd6620a0213351e693b23;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlfaq4.pod b/pod/perlfaq4.pod index 72eb8d8..faccc22 100644 --- a/pod/perlfaq4.pod +++ b/pod/perlfaq4.pod @@ -1,6 +1,6 @@ =head1 NAME -perlfaq4 - Data Manipulation ($Revision: 1.2 $, $Date: 2001/09/26 15:42:12 $) +perlfaq4 - Data Manipulation ($Revision: 1.7 $, $Date: 2001/10/26 19:46:03 $) =head1 DESCRIPTION @@ -123,24 +123,130 @@ Perl numbers whose absolute values are integers under 2**31 (on 32 bit machines) will work pretty much like mathematical integers. Other numbers are not guaranteed. -=head2 How do I convert bits into ints? +=head2 How do I convert between numeric representations: -To turn a string of 1s and 0s like C<10110110> into a scalar containing -its binary value, use the pack() and unpack() functions (documented in -L and L): +As always with Perl there is more than one way to do it. Below +are a few examples of approaches to making common conversions +between number representations. This is intended to be representational +rather than exhaustive. - $decimal = unpack('c', pack('B8', '10110110')); +Some of the examples below use the Bit::Vector module from CPAN. +The reason you might choose Bit::Vector over the perl built in +functions is that it works with numbers of ANY size, that it is +optimized for speed on some operations, and for at least some +programmers the notation might be familiar. -This packs the string C<10110110> into an eight bit binary structure. -This is then unpacked as a character, which returns its ordinal value. +=item B -This does the same thing: +Using perl's built in conversion of 0x notation: + + $int = 0xDEADBEEF; + $dec = sprintf("%d", $int); + +Using the hex function: + + $int = hex("DEADBEEF"); + $dec = sprintf("%d", $int); + +Using pack: + + $int = unpack("N", pack("H8", substr("0" x 8 . "DEADBEEF", -8))); + $dec = sprintf("%d", $int); + +Using the CPAN module Bit::Vector: + + use Bit::Vector; + $vec = Bit::Vector->new_Hex(32, "DEADBEEF"); + $dec = $vec->to_Dec(); + +=item B + +Using sprint: + + $hex = sprintf("%X", 3735928559); + +Using unpack + + $hex = unpack("H*", pack("N", 3735928559)); + +Using Bit::Vector + + use Bit::Vector; + $vec = Bit::Vector->new_Dec(32, -559038737); + $hex = $vec->to_Hex(); + +And Bit::Vector supports odd bit counts: + + use Bit::Vector; + $vec = Bit::Vector->new_Dec(33, 3735928559); + $vec->Resize(32); # suppress leading 0 if unwanted + $hex = $vec->to_Hex(); + +=item B + +Using Perl's built in conversion of numbers with leading zeros: + + $int = 033653337357; # note the leading 0! + $dec = sprintf("%d", $int); + +Using the oct function: + + $int = oct("33653337357"); + $dec = sprintf("%d", $int); + +Using Bit::Vector: + + use Bit::Vector; + $vec = Bit::Vector->new(32); + $vec->Chunk_List_Store(3, split(//, reverse "33653337357")); + $dec = $vec->to_Dec(); + +=item B + +Using sprintf: + + $oct = sprintf("%o", 3735928559); + +Using Bit::Vector + + use Bit::Vector; + $vec = Bit::Vector->new_Dec(32, -559038737); + $oct = reverse join('', $vec->Chunk_List_Read(3)); + +=item B + +Using pack and ord $decimal = ord(pack('B8', '10110110')); -Here's an example of going the other way: +Using pack and unpack for larger strings + + $int = unpack("N", pack("B32", + substr("0" x 32 . "11110101011011011111011101111", -32))); + $dec = sprintf("%d", $int); + + # substr() is used to left pad a 32 character string with zeros. + +Using Bit::Vector: + + $vec = Bit::Vector->new_Bin(32, "11011110101011011011111011101111"); + $dec = $vec->to_Dec(); + +=item B + +Using unpack; + + $bin = unpack("B*", pack("N", 3735928559)); + +Using Bit::Vector: + + use Bit::Vector; + $vec = Bit::Vector->new_Dec(32, -559038737); + $bin = $vec->to_Bin(); + +The remaining transformations (e.g. hex -> oct, bin -> hex, etc.) +are left as an exercise to the inclined reader. - $binary_string = unpack('B*', "\x29"); =head2 Why doesn't & work the way I want it to? @@ -507,6 +613,15 @@ Use Text::Wrap (part of the standard Perl distribution): The paragraphs you give to Text::Wrap should not contain embedded newlines. Text::Wrap doesn't justify the lines (flush-right). +Or use the CPAN module Text::Autoformat. Formatting files can be easily +done by making a shell alias, like so: + + alias fmt="perl -i -MText::Autoformat -n0777 \ + -e 'print autoformat $_, {all=>1}' $*" + +See the documentation for Text::Autoformat to appreciate its many +capabilities. + =head2 How can I access/change the first N letters of a string? There are many ways. If you just want to grab a copy, use @@ -1207,18 +1322,27 @@ Scalar-List-Utils 1.03 or later installed, you can say: If not, you can use this: - # fisher_yates_shuffle( \@array ) : - # generate a random permutation of @array in place + # fisher_yates_shuffle + # generate a random permutation of an array in place + # As in shuffling a deck of cards + # sub fisher_yates_shuffle { - my $array = shift; - my $i = @$array; + my $deck = shift; # $deck is a reference to an array + my $i = @$deck; while (--$i) { my $j = int rand ($i+1); - @$array[$i,$j] = @$array[$j,$i]; + @$deck[$i,$j] = @$deck[$j,$i]; } } - fisher_yates_shuffle( \@array ); # permutes @array in place +And here is an example of using it: + + # + # shuffle my mpeg collection + # + my @mpeg =