⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perlfaq4.pod

📁 MSYS在windows下模拟了一个类unix的终端
💻 POD
📖 第 1 页 / 共 5 页
字号:
=head1 NAMEperlfaq4 - Data Manipulation ($Revision: 1.49 $, $Date: 1999/05/23 20:37:49 $)=head1 DESCRIPTIONThe section of the FAQ answers questions related to the manipulationof data as numbers, dates, strings, arrays, hashes, and miscellaneousdata issues.=head1 Data: Numbers=head2 Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?The infinite set that a mathematician thinks of as the real numbers canonly be approximated on a computer, since the computer only has a finitenumber of bits to store an infinite number of, um, numbers.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 an 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 L<perlvar/"$#"> if you useprint.  C<$#> has a different default value in Perl5 than it did inPerl4.  Changing C<$#> yourself is deprecated.)This affects B<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,C<printf("%.2f", 19.95)>) to get the required precision.See L<perlop/"Floating-point Arithmetic">.  =head2 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=head2 Does Perl have a round() function?  What about ceil() and floor()?  Trig functions?Remember that int() merely truncates toward 0.  For rounding to acertain number of digits, sprintf() or printf() is usually the easiestroute.    printf("%.3f", 3.1415926535);	# prints 3.142The POSIX module (part of the standard Perl distribution) implementsceil(), floor(), and a number of other mathematical and trigonometricfunctions.    use POSIX;    $ceil   = ceil(3.5);			# 4    $floor  = floor(3.5);			# 3In 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.To see why, notice how you'll still have an issue on half-way-pointalternation:    for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}    0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7     0.8 0.8 0.9 0.9 1.0 1.0Don't blame Perl.  It's the same as in C.  IEEE says we have to do this.Perl numbers whose absolute values are integers under 2**31 (on 32 bitmachines) will work pretty much like mathematical integers.  Other numbersare not guaranteed.=head2 How do I convert bits into ints?To turn a string of 1s and 0s like C<10110110> into a scalar containingits binary value, use the pack() and unpack() functions (documented inL<perlfunc/"pack"> and L<perlfunc/"unpack">):    $decimal = unpack('c', pack('B8', '10110110'));This packs the string C<10110110> into an eight bit binary structure.This is then unpacked as a character, which returns its ordinal value.This does the same thing:    $decimal = ord(pack('B8', '10110110'));Here's an example of going the other way:    $binary_string = unpack('B*', "\x29");=head2 Why doesn't & work the way I want it to?The behavior of binary arithmetic operators depends on whether they'reused on numbers or strings.  The operators treat a string as a seriesof bits and work with that (the string C<"3"> is the bit patternC<00110011>).  The operators work with the binary form of a number(the number C<3> is treated as the bit pattern C<00000011>).So, saying C<11 & 3> performs the "and" operation on numbers (yieldingC<1>).  Saying C<"11" & "3"> performs the "and" operation on strings(yielding C<"1">).Most problems with C<&> and C<|> arise because the programmer thinksthey have a number but really it's a string.  The rest arise becausethe programmer says:    if ("\020\020" & "\101\101") {	# ...    }but a string consisting of two null bytes (the result of C<"\020\020"& "\101\101">) is not a false value in Perl.  You need:    if ( ("\020\020" & "\101\101") !~ /[^\000]/) {	# ...    }=head2 How do I multiply matrices?Use the Math::Matrix or Math::MatrixReal modules (available from CPAN)or the PDL extension (also available from CPAN).=head2 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) {        some_func($iterator);    }To call a function on each integer in a (small) range, you B<can> use:    @results = map { some_func($_) } (5 .. 25);but you should be aware that the C<..> 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, some_func($i));    }This situation has been fixed in Perl5.005. Use of C<..> in a C<for>loop will iterate over the range, without creating the entire range.    for my $i (5 .. 500_005) {        push(@results, some_func($i));    }will not create a list of 500,000 integers.=head2 How can I output Roman numerals?Get the http://www.perl.com/CPAN/modules/by-module/Roman module.=head2 Why aren't my random numbers random?If you're using a version of Perl before 5.004, you must call C<srand>once at the start of your program to seed the random number generator.5.004 and later automatically call C<srand> at the beginning.  Don'tcall C<srand> more than once--you make your numbers less random, ratherthan more.Computers are good at being predictable and bad at being random(despite appearances caused by bugs in your programs :-).http://www.perl.com/CPAN/doc/FMTEYEWTK/random , courtesy of TomPhoenix, talks more about this.  John von Neumann said, ``Anyone whoattempts to generate random numbers by deterministic means is, ofcourse, living in a state of sin.''If you want numbers that are more random than C<rand> with C<srand>provides, you should also check out the Math::TrulyRandom module fromCPAN.  It uses the imperfections in your system's timer to generaterandom numbers, but this takes quite a while.  If you want a betterpseudorandom generator than comes with your operating system, look at``Numerical Recipes in C'' at http://www.nr.com/ .=head1 Data: Dates=head2 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() (seeL<perlfunc/"localtime">):    $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.  The Date::Calcmodule from CPAN has a lot of date calculation functions, includingday of the year, week of the year, and so on.   Note that notall businesses consider ``week 1'' to be the same; for example,American businesses often consider the first week with a Mondayin it to be Work Week #1, despite ISO 8601, which considersWW1 to be the first week with a Thursday in it.=head2 How do I find the current century or millennium?Use the following simple functions:    sub get_century    { 	return int((((localtime(shift || time))[5] + 1999))/100);    }     sub get_millennium { 	return 1+int((((localtime(shift || time))[5] + 1899))/1000);    } On some systems, you'll find that the POSIX module's strftime() functionhas been extended in a non-standard way to use a C<%C> format, which theysometimes claim is the "century".  It isn't, because on most such systems,this is only the first two digits of the four-digit year, and thus cannotbe used to reliably determine the current century or millennium.=head2 How can I compare two dates and find the difference?If you're storing your dates as epoch seconds then simply subtract onefrom the other.  If you've got a structured date (distinct year, day,month, hour, minute, seconds values), then for reasons of accessibility,simplicity, and efficiency, merely use either timelocal or timegm (fromthe Time::Local module in the standard distribution) to reduce structureddates to epoch seconds.  However, if you don't know the precise format ofyour dates, then you should probably use either of the Date::Manip andDate::Calc modules from CPAN before you go hacking up your own parsingroutine to handle arbitrary date formats.=head2 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 C<timelocal> in the standardTime::Local module.  Otherwise, you should look into the Date::Calcand Date::Manip modules from CPAN.=head2 How can I find the Julian Day?Use the Time::JulianDay module (part of the Time-modules bundleavailable from CPAN.)Before you immerse yourself too deeply in this, be sure to verify that itis the I<Julian> Day you really want.  Are you really just interested ina way of getting serial days so that they can do date arithmetic?  If youare interested in performing date arithmetic, this can be done usingeither Date::Manip or Date::Calc, without converting to Julian Day first.There is too much confusion on this issue to cover in this FAQ, but theterm is applied (correctly) to a calendar now supplanted by the GregorianCalendar, with the Julian Calendar failing to adjust properly for leapyears on centennial years (among other annoyances).  The term is also used(incorrectly) to mean: [1] days in the Gregorian Calendar; and [2] dayssince a particular starting time or `epoch', usually 1970 in the Unixworld and 1980 in the MS-DOS/Windows world.  If you find that it is notthe first meaning that you really want, then check out the Date::Manipand Date::Calc modules.  (Thanks to David Cassell for most of this text.)=head2 How do I find yesterday's date?The C<time()> function returns the current time in seconds since theepoch.  Take twenty-four hours off that:    $yesterday = time() - ( 24 * 60 * 60 );Then you can pass this to C<localtime()> and get the individual year,month, day, hour, minute, seconds values.Note very carefully that the code above assumes that your days aretwenty-four hours each.  For most people, there are two days a yearwhen they aren't: the switch to and from summer time throws this off.A solution to this issue is offered by Russ Allbery.    sub yesterday {	my $now  = defined $_[0] ? $_[0] : time;	my $then = $now - 60 * 60 * 24;	my $ndst = (localtime $now)[8] > 0;	my $tdst = (localtime $then)[8] > 0;	$then - ($tdst - $ndst) * 60 * 60;    }    # Should give you "this time yesterday" in seconds since epoch relative to    # the first argument or the current time if no argument is given and    # suitable for passing to localtime or whatever else you need to do with    # it.  $ndst is whether we're currently in daylight savings time; $tdst is    # whether the point 24 hours ago was in daylight savings time.  If $tdst    # and $ndst are the same, a boundary wasn't crossed, and the correction    # will subtract 0.  If $tdst is 1 and $ndst is 0, subtract an hour more    # from yesterday's time since we gained an extra hour while going off    # daylight savings time.  If $tdst is 0 and $ndst is 1, subtract a    # negative hour (add an hour) to yesterday's time since we lost an hour.    #    # All of this is because during those days when one switches off or onto    # DST, a "day" isn't 24 hours long; it's either 23 or 25.    #    # The explicit settings of $ndst and $tdst are necessary because localtime    # only says it returns the system tm struct, and the system tm struct at    # least on Solaris doesn't guarantee any particular positive value (like,    # say, 1) for isdst, just a positive value.  And that value can    # potentially be negative, if DST information isn't available (this sub    # just treats those cases like no DST).    #    # Note that between 2am and 3am on the day after the time zone switches    # off daylight savings time, the exact hour of "yesterday" corresponding    # to the current hour is not clearly defined.  Note also that if used    # between 2am and 3am the day after the change to daylight savings time,    # the result will be between 3am and 4am of the previous day; it's    # arguable whether this is correct.    #    # This sub does not attempt to deal with leap seconds (most things don't).    #    # Copyright relinquished 1999 by Russ Allbery <rra@stanford.edu>    # This code is in the public domain=head2 Does Perl have a Year 2000 problem?  Is Perl Y2K compliant?Short answer: No, Perl does not have a Year 2000 problem.  Yes, Perl isY2K compliant (whatever that means).  The programmers you've hired touse it, however, probably are not.Long answer: The question belies a true understanding of the issue.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -