MAN page from Old RedHat 5.X perl-5.004-4.i386.rpm
PERLFAQ4
Section: Perl Programmers Reference Guide (1)
Updated: perl 5.004, patch 04
Index NAME
perlfaq4 - Data Manipulation ($Revision: 1.19 $,
$Date: 1997/04/24 22:43:57 $)
DESCRIPTION
The section of the FAQ answers question related to the manipulationof data as numbers, dates, strings, arrays, hashes, and miscellaneousdata issues.
Data: Numbers
Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?
Internally, your computer represents floating-point numbers in binary.Floating-point numbers read in from a file, or appearing as literalsin your program, are converted from their decimal floating-pointrepresentation (eg, 19.95) to the internal binary representation.
However, 19.95 can't be precisely represented as a binaryfloating-point number, just like 1/3 can't be exactly represented as adecimal floating-point number. The computer's binary representationof 19.95, therefore, isn't exactly 19.95.
When a floating-point number gets printed, the binary floating-pointrepresentation is converted back to decimal. These decimal numbersare displayed in either the format you specify with printf(), or thecurrent output format for numbers (see the section on $# in the perlvar manpage if you useprint. $# has a different default value in Perl5 than it did inPerl4. Changing $# yourself is deprecated.
This affects all computer languages that represent decimalfloating-point numbers in binary, not just Perl. Perl providesarbitrary-precision decimal numbers with the Math::BigFloat module(part of the standard Perl distribution), but mathematical operationsare consequently slower.
To get rid of the superfluous digits, just use a format (eg,printf("%.2f", 19.95)) to get the required precision.
Why isn't my octal data interpreted correctly?
Perl only understands octal and hex numbers as such when they occuras literals in your program. If they are read in from somewhere andassigned, no automatic conversion takes place. You must explicitlyuse
oct() or
hex() if you want the values converted.
oct() interpretsboth hex ("0x350") numbers and octal ones ("0350'' or even without theleading ``0'', like ``377"), while
hex() only converts hexadecimal ones,with or without a leading ``0x'', like ``0x255'', ``3A'', ``ff'', or ``deadbeef''.
This problem shows up most often when people try using chmod(), mkdir(),umask(), or sysopen(), which all want permissions in octal.
chmod(644, $file); # WRONG -- perl -w catches this chmod(0644, $file); # right
Does perl have a round function? What about ceil() and floor()? Trig functions?
For rounding to a certain number of digits,
sprintf() or
printf() isusually the easiest route.
The POSIX module (part of the standard perl distribution) implementsceil(), floor(), and a number of other mathematical and trigonometricfunctions.
In 5.000 to 5.003 Perls, trigonometry was done in the Math::Complexmodule. With 5.004, the Math::Trig module (part of the standard perldistribution) implements the trigonometric functions. Internally ituses the Math::Complex module and some functions can break out fromthe real axis into the complex plane, for example the inverse sine of2.
Rounding in financial applications can have serious implications, andthe rounding method used should be specified precisely. In thesecases, it probably pays not to trust whichever system rounding isbeing used by Perl, but to instead implement the rounding function youneed yourself.
How do I convert bits into ints?
To turn a string of 1s and 0s like `10110110' into a scalar containingits binary value, use the
pack() function (documented inthe section on
pack in the
perlfunc manpage):
$decimal = pack('B8', '10110110');Here's an example of going the other way:
$binary_string = join('', unpack('B*', "\x29")); How do I multiply matrices?
Use the Math::Matrix or Math::MatrixReal modules (available from
CPAN)or the
PDL extension (also available from
CPAN).
How do I perform an operation on a series of integers?
To call a function on each element in an array, and collect theresults, use:
@results = map { my_func($_) } @array;For example:
@triple = map { 3 * $_ } @single;To call a function on each element of an array, but ignore theresults:
foreach $iterator (@array) { &my_func($iterator); }To call a function on each integer in a (small) range, you
can use:
@results = map { &my_func($_) } (5 .. 25);but you should be aware that the
.. operator creates an array ofall integers in the range. This can take a lot of memory for largeranges. Instead use:
@results = (); for ($i=5; $i < 500_005; $i++) { push(@results, &my_func($i)); } How can I output Roman numerals?
Get the
http://www.perl.com/CPAN/modules/by-module/Roman module.
Why aren't my random numbers random?
The short explanation is that you're getting pseudorandom numbers, notrandom ones, because that's how these things work. A longerexplanation is available on
http://www.perl.com/CPAN/doc/
FMTEYEWTK/random, courtesy of TomPhoenix.
You should also check out the Math::TrulyRandom module from CPAN.
Data: Dates
How do I find the week-of-the-year/day-of-the-year?
The day of the year is in the array returned by
localtime() (seethe section on
localtime in the
perlfunc manpage):
$day_of_year = (localtime(time()))[7];
or more legibly (in 5.004 or higher):
use Time::localtime; $day_of_year = localtime(time())->yday;
You can find the week of the year by dividing this by 7:
$week_of_year = int($day_of_year / 7);
Of course, this believes that weeks start at zero.
How can I compare two date strings?
Use the Date::Manip or Date::DateCalc modules from
CPAN.
How can I take a string and turn it into epoch seconds?
If it's a regular enough string that it always has the same format,you can split it up and pass the parts to timelocal in the standard