perlfaq4.html
来自「perl教程」· HTML 代码 · 共 867 行 · 第 1/5 页
HTML
867 行
<p>Your <a href="../../lib/Pod/perlfunc.html#item_int"><code>int()</code></a> is most probably working just fine. It's the numbers that
aren't quite what you think.</p>
<p>First, see the above item "Why am I getting long decimals
(eg, 19.9499999999999) instead of the numbers I should be getting
(eg, 19.95)?".</p>
<p>For example, this</p>
<pre>
<span class="keyword">print</span> <span class="keyword">int</span><span class="operator">(</span><span class="number">0</span><span class="operator">.</span><span class="number">6</span><span class="operator">/</span><span class="number">0</span><span class="operator">.</span><span class="number">2</span><span class="operator">-</span><span class="number">2</span><span class="operator">),</span> <span class="string">"\n"</span><span class="operator">;</span>
</pre>
<p>will in most computers print 0, not 1, because even such simple
numbers as 0.6 and 0.2 cannot be presented exactly by floating-point
numbers. What you think in the above as 'three' is really more like
2.9999999999999995559.</p>
<p>
</p>
<h2><a name="why_isn_t_my_octal_data_interpreted_correctly">Why isn't my octal data interpreted correctly?</a></h2>
<p>Perl only understands octal and hex numbers as such when they occur as
literals in your program. Octal literals in perl must start with a
leading "0" and hexadecimal literals must start with a leading "0x".
If they are read in from somewhere and assigned, no automatic
conversion takes place. You must explicitly use <a href="../../lib/Pod/perlfunc.html#item_oct"><code>oct()</code></a> or <a href="../../lib/Pod/perlfunc.html#item_hex"><code>hex()</code></a> if you
want the values converted to decimal. <a href="../../lib/Pod/perlfunc.html#item_oct"><code>oct()</code></a> interprets hex ("0x350"),
octal ("0350" or even without the leading "0", like "377") and binary
("0b1010") numbers, while <a href="../../lib/Pod/perlfunc.html#item_hex"><code>hex()</code></a> only converts hexadecimal ones, with
or without a leading "0x", like "0x255", "3A", "ff", or "deadbeef".
The inverse mapping from decimal to octal can be done with either the
"%o" or "%O" <a href="../../lib/Pod/perlfunc.html#item_sprintf"><code>sprintf()</code></a> formats.</p>
<p>This problem shows up most often when people try using chmod(), mkdir(),
umask(), or sysopen(), which by widespread tradition typically take
permissions in octal.</p>
<pre>
<span class="keyword">chmod</span><span class="operator">(</span><span class="number">644</span><span class="operator">,</span> <span class="variable">$file</span><span class="operator">);</span> <span class="comment"># WRONG</span>
<span class="keyword">chmod</span><span class="operator">(</span><span class="number">0644</span><span class="operator">,</span> <span class="variable">$file</span><span class="operator">);</span> <span class="comment"># right</span>
</pre>
<p>Note the mistake in the first line was specifying the decimal literal
644, rather than the intended octal literal 0644. The problem can
be seen with:</p>
<pre>
<span class="keyword">printf</span><span class="operator">(</span><span class="string">"%#o"</span><span class="operator">,</span><span class="number">644</span><span class="operator">);</span> <span class="comment"># prints 01204</span>
</pre>
<p>Surely you had not intended <a href="../../lib/Pod/perlfunc.html#item_chmod"><code>chmod(01204, $file);</code></a> - did you? If you
want to use numeric literals as arguments to <a href="../../lib/Pod/perlfunc.html#item_chmod"><code>chmod()</code></a> et al. then please
try to express them as octal constants, that is with a leading zero and
with the following digits restricted to the set 0..7.</p>
<p>
</p>
<h2><a name="does_perl_have_a_round___function_what_about_ceil___and_floor___trig_functions">Does Perl have a <code>round()</code> function? What about <code>ceil()</code> and floor()? Trig functions?</a></h2>
<p>Remember that <a href="../../lib/Pod/perlfunc.html#item_int"><code>int()</code></a> merely truncates toward 0. For rounding to a
certain number of digits, <a href="../../lib/Pod/perlfunc.html#item_sprintf"><code>sprintf()</code></a> or <a href="../../lib/Pod/perlfunc.html#item_printf"><code>printf()</code></a> is usually the easiest
route.</p>
<pre>
<span class="keyword">printf</span><span class="operator">(</span><span class="string">"%.3f"</span><span class="operator">,</span> <span class="number">3.1415926535</span><span class="operator">);</span> <span class="comment"># prints 3.142</span>
</pre>
<p>The POSIX module (part of the standard Perl distribution) implements
ceil(), floor(), and a number of other mathematical and trigonometric
functions.</p>
<pre>
<span class="keyword">use</span> <span class="variable">POSIX</span><span class="operator">;</span>
<span class="variable">$ceil</span> <span class="operator">=</span> <span class="variable">ceil</span><span class="operator">(</span><span class="number">3.5</span><span class="operator">);</span> <span class="comment"># 4</span>
<span class="variable">$floor</span> <span class="operator">=</span> <span class="variable">floor</span><span class="operator">(</span><span class="number">3.5</span><span class="operator">);</span> <span class="comment"># 3</span>
</pre>
<p>In 5.000 to 5.003 perls, trigonometry was done in the Math::Complex
module. With 5.004, the Math::Trig module (part of the standard Perl
distribution) implements the trigonometric functions. Internally it
uses the Math::Complex module and some functions can break out from
the real axis into the complex plane, for example the inverse sine of
2.</p>
<p>Rounding in financial applications can have serious implications, and
the rounding method used should be specified precisely. In these
cases, it probably pays not to trust whichever system rounding is
being used by Perl, but to instead implement the rounding function you
need yourself.</p>
<p>To see why, notice how you'll still have an issue on half-way-point
alternation:</p>
<pre>
<span class="keyword">for</span> <span class="operator">(</span><span class="variable">$i</span> <span class="operator">=</span> <span class="number">0</span><span class="operator">;</span> <span class="variable">$i</span> <span class="operator"><</span> <span class="number">1.01</span><span class="operator">;</span> <span class="variable">$i</span> <span class="operator">+=</span> <span class="number">0</span><span class="operator">.</span><span class="number">05</span><span class="operator">)</span> <span class="operator">{</span> <span class="keyword">printf</span> <span class="string">"%.1f "</span><span class="operator">,</span><span class="variable">$i</span><span class="operator">}</span>
</pre>
<pre>
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.0</pre>
<p>Don'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 bit
machines) will work pretty much like mathematical integers. Other numbers
are not guaranteed.</p>
<p>
</p>
<h2><a name="how_do_i_convert_between_numeric_representations_bases_radixes">How do I convert between numeric representations/bases/radixes?</a></h2>
<p>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.</p>
<p>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.</p>
<dl>
<dt><strong><a name="item_how_do_i_convert_hexadecimal_into_decimal">How do I convert hexadecimal into decimal</a></strong>
<dd>
<p>Using perl's built in conversion of 0x notation:</p>
</dd>
<dd>
<pre>
<span class="variable">$dec</span> <span class="operator">=</span> <span class="number">0xDEADBEEF</span><span class="operator">;</span>
</pre>
</dd>
<dd>
<p>Using the hex function:</p>
</dd>
<dd>
<pre>
<span class="variable">$dec</span> <span class="operator">=</span> <span class="keyword">hex</span><span class="operator">(</span><span class="string">"DEADBEEF"</span><span class="operator">);</span>
</pre>
</dd>
<dd>
<p>Using pack:</p>
</dd>
<dd>
<pre>
<span class="variable">$dec</span> <span class="operator">=</span> <span class="keyword">unpack</span><span class="operator">(</span><span class="string">"N"</span><span class="operator">,</span> <span class="keyword">pack</span><span class="operator">(</span><span class="string">"H8"</span><span class="operator">,</span> <span class="keyword">substr</span><span class="operator">(</span><span class="string">"0"</span> <span class="operator">x</span> <span class="number">8</span> <span class="operator">.</span> <span class="string">"DEADBEEF"</span><span class="operator">,</span> <span class="operator">-</span><span class="number">8</span><span class="operator">)));</span>
</pre>
</dd>
<dd>
<p>Using the CPAN module Bit::Vector:</p>
</dd>
<dd>
<pre>
<span class="keyword">use</span> <span class="variable">Bit::Vector</span><span class="operator">;</span>
<span class="variable">$vec</span> <span class="operator">=</span> <span class="variable">Bit::Vector</span><span class="operator">-></span><span class="variable">new_Hex</span><span class="operator">(</span><span class="number">32</span><span class="operator">,</span> <span class="string">"DEADBEEF"</span><span class="operator">);</span>
<span class="variable">$dec</span> <span class="operator">=</span> <span class="variable">$vec</span><span class="operator">-></span><span class="variable">to_Dec</span><span class="operator">();</span>
</pre>
</dd>
</li>
<dt><strong><a name="item_how_do_i_convert_from_decimal_to_hexadecimal">How do I convert from decimal to hexadecimal</a></strong>
<dd>
<p>Using sprintf:</p>
</dd>
<dd>
<pre>
<span class="variable">$hex</span> <span class="operator">=</span> <span class="keyword">sprintf</span><span class="operator">(</span><span class="string">"%X"</span><span class="operator">,</span> <span class="number">3735928559</span><span class="operator">);</span> <span class="comment"># upper case A-F</span>
<span class="variable">$hex</span> <span class="operator">=</span> <span class="keyword">sprintf</span><span class="operator">(</span><span class="string">"%x"</span><span class="operator">,</span> <span class="number">3735928559</span><span class="operator">);</span> <span class="comment"># lower case a-f</span>
</pre>
</dd>
<dd>
<p>Using unpack:</p>
</dd>
<dd>
<pre>
<span class="variable">$hex</span> <span class="operator">=</span> <span class="keyword">unpack</span><span class="operator">(</span><span class="string">"H*"</span><span class="operator">,</span> <span class="keyword">pack</span><span class="operator">(</span><span class="string">"N"</span><span class="operator">,</span> <span class="number">3735928559</span><span class="operator">));</span>
</pre>
</dd>
<dd>
<p>Using Bit::Vector:</p>
</dd>
<dd>
<pre>
<span class="keyword">use</span> <span class="variable">Bit::Vector</span><span class="operator">;</span>
<span class="variable">$vec</span> <span class="operator">=</span> <span class="variable">Bit::Vector</span><span class="operator">-></span><span class="variable">new_Dec</span><span class="operator">(</span><span class="number">32</span><span class="operator">,</span> <span class="operator">-</span><span class="number">559038737</span><span class="operator">);</span>
<span class="variable">$hex</span> <span class="operator">=</span> <span class="variable">$vec</span><span class="operator">-></span><span class="variable">to_Hex</span><span class="operator">();</span>
</pre>
</dd>
<dd>
<p>And Bit::Vector supports odd bit counts:</p>
</dd>
<dd>
<pre>
<span class="keyword">use</span> <span class="variable">Bit::Vector</span><span class="operator">;</span>
<span class="variable">$vec</span> <span class="operator">=</span> <span class="variable">Bit::Vector</span><span class="operator">-></span><span class="variable">new_Dec</span><span class="operator">(</span><span class="number">33</span><span class="operator">,</span> <span class="number">3735928559</span><span class="operator">);</span>
<span class="variable">$vec</span><span class="operator">-></span><span class="variable">Resize</span><span class="operator">(</span><span class="number">32</span><span class="operator">);</span> <span class="comment"># suppress leading 0 if unwanted</span>
<span class="variable">$hex</span> <span class="operator">=</span> <span class="variable">$vec</span><span class="operator">-></span><span class="variable">to_Hex</span><span class="operator">();</span>
</pre>
</dd>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?