用于pi计算的Perl代码

用于pi计算的Perl代码,perl,Perl,有人能用Perl一步一步地解释一下这段代码吗: $.=.5; $\=2/$.++-$\for$...1e6; print 添加空白: $. = .5; $\ = (2 / $.++) - $\ for $. .. 1e6; 用saner var名称替换: $x = .5; $pi = (2 / $x++) - $pi for $x .. 1e6; 不要将同一var用于两个目的: $x = .5; $pi = (2 / $x++) - $pi for 0 .. 1e6; 转换为公式: pi

有人能用Perl一步一步地解释一下这段代码吗:

$.=.5;
$\=2/$.++-$\for$...1e6;
print
添加空白:

$. = .5;
$\ = (2 / $.++) - $\ for $. .. 1e6;
用saner var名称替换:

$x = .5;
$pi = (2 / $x++) - $pi for $x .. 1e6;
不要将同一var用于两个目的:

$x = .5;
$pi = (2 / $x++) - $pi for 0 .. 1e6;
转换为公式:

pi = 2/1000000.5 - ( ... - (2/2.5 - (2/1.5 - (2/0.5))))

   = 2/1000000.5 - ... + 2/2.5 - 2/1.5 + 2/0.5

   = 4/2000001 - ... + 4/5 - 4/3 + 4/1

   = 4/1 - 4/3 + 4/5 - ... + 4/2000001
这在维基百科中被称为格雷戈里-莱布尼兹系列


打印是<代码>打印($)
,它打印
$\uuu
(未使用,因此未定义,字符串化为空字符串),后跟
$\
(通常为空字符串,但在原始代码中用作累加器)。

这可以重写为:

use strict;
use warnings;

my $divisor = 0.5;
my $pi = 0;
for my $i (0..1e6)
{
    $pi = 2 / $divisor++ - $pi
}
print "$pi\n";

因此,它使用一些数学级数展开来计算pi(请参见@ikegami的答案)

首先,让我们将代码分解为更可读的部分,并使用一些空格。在Perl中,空白相对不重要

$. = .5;
$\ = 2 / $.++ - $\ for $. .. 1e6;
print
这段代码使用Perl的特殊内置全局变量使事情看起来简短(
ManPerlVar
了解有关这段代码使用的特定变量的更多详细信息)。让我们将其替换为人类可读的名称,使其更具可读性

$denominator = .5;
$pi = 2 / $denominator++ - $pi for $denominator .. 1e6
print $pi
为了提供帮助,让我们将内联for循环移动到更详细的循环中

$denominator = .5;
foreach my $i ($denominator .. 1e6) {
  $pi = 2 / $denominator - $pi;
  $denominator += 1;
}
print $pi
所以,这使得它更容易破译,这是计算pi的标准收敛程序。有很多,但基本上,如果你通过它,你会看到它收敛到著名的3.14159。。。分母可以用作序列生成器的第一个元素,因为它将下限为整数0

Pass 1: 2 / 0.5 - 0 = 4
Pass 2: 2 / 1.5 - 4 = -2.666...
Pass 3: 2 / 2.5 - (-2.666...) = 3.4666...
Pass 4: 2 / 3.5 - 3.4666... = -2.895...
Pass 5: 2 / 4.5 - (-2.895...) = 3.339...
你明白了。代码运行1000001次,以达到最终近似值。只要它运行奇数个近似值,它就应该收敛到pi(偶数个近似值收敛到负pi)


print语句工作的原因是,
$\
是输出记录分隔符
print
本身将打印默认变量
$\ucode>,该变量将为空。pi的值将在
$\
值中,这实际上是行尾,因此它会打印出一个空白值,后跟pi的计算值(没有传统的行尾)。

哇,这真是太美了。有人试图让它看起来尽可能复杂。以下是更具可读性的版本:

my $pi = 0;
for (my $i=0.5; $i < 1e6+1; $i++)
{
    $pi=2/$i - $pi;
}
print $pi."\n";
my$pi=0;
对于(我的$i=0.5;$i<1e6+1;$i++)
{
$pi=2/$i-$pi;
}
打印$pi。“\n”;
这是该模型的数学表示


最初的版本使用了一些方法来迷惑你。
$。
在这里完全没有必要,纯粹是为了混淆。
$\
输出记录分隔符。这意味着该变量将附加在
print
语句之后。因此,最后的单个
print
仅打印存储在
$\
中的计算结果。最后,代码对
循环和。操作符使用后修复
,而不是我的版本中更明确的for循环。我希望这能让事情澄清一点。

你没有解释单一的“打印”。清晰,向上投票,我认为这应该添加到你的帖子中。从技术上讲,它只打印了$pi而不是
打印“$pi\n”
@ikegami:true,但不打印尾随的换行符会弄乱我的提示:)
对于我的$i(0..1e6){…2/($i+0.5)}
要比对于(我的$i=0.5;$i<1e6+1;$i++{…2/$i…}
简单得多。我的主要观点是使for循环显式地表示为a-la C或Java,以避免潜在的混乱
语法。但最终,这取决于OP不理解代码的哪一部分:-)我的观点正好相反;C型循环太糟糕了。它们是如此复杂,以至于我们要么需要费力通过九个运营商,要么就这些运营商是什么进行假设。与计数循环(
for(1..5)
)的两个运算符相比,这两个选项都非常糟糕。这不是“潜在的混乱”;这是清晰的最好例子!潜在的困惑是必须寻找一条符号密集的线,看看
是否没有弄错:我同意这一点。但是对于从未接触过Perl或者现在不了解该语言特性的人来说,
操作符可能不如-丑陋-
for
循环熟悉