【问题标题】:perl6: why is array skipping calculated values inside declaration?perl6:为什么数组在声明中跳过计算值?
【发布时间】:2019-01-15 16:50:12
【问题描述】:

我正在从 Perl5 学习 Perl6。

为了使这个编译,我将发布整个程序:

sub lgamma ( Num(Real) \n --> Num ){
  use NativeCall;
  sub lgamma (num64 --> num64) is native {}
  lgamma( n )
}

sub pvalue (@a, @b) {
  if @a.elems <= 1 {
    return 1.0;
  }
  if @b.elems <= 1 {
    return 1.0;
  }
  my Rat $mean1 = @a.sum / @a.elems;
  my Rat $mean2 = @b.sum / @b.elems;
  if $mean1 == $mean2 {
    return 1.0;
  }
  my Rat $variance1 = 0.0;
  my Rat $variance2 = 0.0;

  for @a -> $i {
    $variance1 += ($mean1 - $i)**2#";" unnecessary for last statement in block
  }
  for @b -> $i {
    $variance2 += ($mean2 - $i)**2
  }
  if ($variance1 == 0 && $variance2 == 0) {
    return 1.0;
  }
  $variance1 /= (@a.elems - 1);
  $variance2 /= (@b.elems - 1);

  my $WELCH_T_STATISTIC = ($mean1-$mean2)/sqrt($variance1/@a.elems+$variance2/@b.elems);
    my $DEGREES_OF_FREEDOM = (($variance1/@a.elems+$variance2/@b.elems)**2)
    /
    (
    ($variance1*$variance1)/(@a.elems*@a.elems*(@a.elems-1))+
    ($variance2*$variance2)/(@b.elems*@b.elems*(@b.elems-1))
    );
    my $A = $DEGREES_OF_FREEDOM/2;
    my $value = $DEGREES_OF_FREEDOM/($WELCH_T_STATISTIC*$WELCH_T_STATISTIC+$DEGREES_OF_FREEDOM);
  my Num $beta = lgamma($A)+0.57236494292470009-lgamma($A+0.5);
    my Rat $acu = 10**(-15);
    my ($ai,$cx,$indx,$ns,$pp,$psq,$qq,$rx,$temp,$term,$xx);
# Check the input arguments.
    return $value if $A <= 0.0;# || $q <= 0.0;
    return $value if $value < 0.0 || 1.0 < $value;
# Special cases
    return $value if $value == 0.0 || $value == 1.0;
    $psq = $A + 0.5;
    $cx = 1.0 - $value;
    if $A < $psq * $value {
        ($xx, $cx, $pp, $qq, $indx) = ($cx, $value, 0.5, $A, 1);
    } else {
        ($xx, $pp, $qq, $indx) = ($value, $A, 0.5, 0);
    }
    $term = 1.0;
    $ai = 1.0;
    $value = 1.0;
    $ns = $qq + $cx * $psq;
  $ns = $ns.Int;
#Soper reduction formula.
    $rx = $xx / $cx;
    $temp = $qq - $ai;
    $rx = $xx if $ns == 0;
    while (True) {
        $term = $term * $temp * $rx / ( $pp + $ai );
        $value = $value + $term;
        $temp = $term.abs;
        if $temp <= $acu && $temp <= $acu * $value {
        $value = $value * ($pp * $xx.log + ($qq - 1.0) * $cx.log - $beta).exp / $pp;
        $value = 1.0 - $value if $indx;
        last;
        }
        $ai++;
        $ns--;
        if 0 <= $ns {
            $temp = $qq - $ai;
            $rx = $xx if $ns == 0;
        } else {
            $temp = $psq;
            $psq = $psq + 1.0;
        }
    }
    return $value;
}

my @array2d = ([27.5,21.0,19.0,23.6,17.0,17.9,16.9,20.1,21.9,22.6,23.1,19.6,19.0,21.7,21.4],
 [27.1,22.0,20.8,23.4,23.4,23.5,25.8,22.0,24.8,20.2,21.9,22.1,22.9,20.5,24.4],#0.

 [17.2,20.9,22.6,18.1,21.7,21.4,23.5,24.2,14.7,21.8],
 [21.5,22.8,21.0,23.0,21.6,23.6,22.5,20.7,23.4,21.8,20.7,21.7,21.5,22.5,23.6,21.5,22.5,23.5,21.5,21.8],

 [19.8,20.4,19.6,17.8,18.5,18.9,18.3,18.9,19.5,22.0],
 [28.2,26.6,20.1,23.3,25.2,22.1,17.7,27.6,20.6,13.7,23.2,17.5,20.6,18.0,23.9,21.6,24.3,20.4,24.0,13.2],

 [30.02,29.99,30.11,29.97,30.01,29.99],
 [29.89,29.93,29.72,29.98,30.02,29.98],

 [3.0,4.0,1.0,2.1],
 [490.2,340.0,433.9],

 [<1.0/15.0>, <10.0/62.0>],
 [<1.0/10>, <2/50.0>],

 [0.010268,0.000167,0.000167],
 [0.159258,0.136278,0.122389],

 [9/23.0,21/45.0,0/38.0],
 [0/44.0,42/94.0,0/22.0]);

 say @array2d[11][0];

 my @CORRECT_ANSWERS = (0.021378001462867,
 0.148841696605327,
 0.0359722710297968,
 0.090773324285671,
 0.0107515611497845,
 0.00339907162713746,
 0.52726574965384,
 0.545266866977794);

my UInt $i = 0;
my Real $error = 0.0;
for @array2d -> @left, @right {
  my $pvalue = pvalue(@left, @right);
  $error += ($pvalue - @CORRECT_ANSWERS[$i]).abs;
  say "$i [" ~ @left.join(',') ~ '] [' ~ @right ~ "] = $pvalue";
  if $error > 10**-9 {
    say "\$p = $pvalue, but should be @CORRECT_ANSWERS[$i]";
    die;
  }
#  printf("Test sets %u p-value = %.14g\n",$i+1,$pvalue);
  $i++
}

printf("the cumulative error is %g\n", $error);

这个子数组的不同之处在于它有“/”表示除法。如何让 Perl6 for 循环评估这个子数组?

编辑:我正在努力研究构成最小工作示例的内容。我将发布整个代码以便编译。

【问题讨论】:

  • 首先,即使您也在一个简单的数组中执行此操作,也会发生这种情况。其次,它被评估为一只老鼠。如果 Rats 在数组中,它恰好以这种方式打印。如果您使用 say、put 或 print,它将被 Num-ified 到 0.161...如果您将它们声明为列表的一部分,则相同。是同一个号码。
  • @jjmerelo “首先,即使你在一个简单的数组中执行它也会发生。”我已经编辑了这个问题,在我看来,像我展示的一维数组,它被评估了,这是你的意思吗?
  • 关键是它的显示方式很简单。当您使用它时,价值将是相同的。如果要显示小数点,只需添加 .Num 即可。
  • 1.0/15.01/15 完全相同 与Rat.new(1,15) 完全相同。我运行了你的代码,这些计算确实发生了。你打电话给.perl 还是dd?两者都会打印&lt;1/15&gt;,但那是因为有重复的数字。
  • 嗨@con。让我总结一下我对您问题的三个(!!!)答案。我是"sure" 我的第三个也是最后一个答案 是对的。这只是一个数据错误。我希望我的第二个 (Rewrite) "nanswer" (not-at-answer) 有一些价值。我的第一个(出了什么问题?)“sanswer”(没有答案的答案)希望能减少而不是增加对Rats 的恐惧。总而言之,这是一次有趣的桑树之旅。正如他们所说,这是关于旅程,而不是目的地。 :)

标签: raku


【解决方案1】:

(事实证明,这个答案完全忽略了@con 的问题。但我不会删除它,因为它收集了一些关于有理数的有用链接。)

怎么了?

为什么数组会在声明中跳过计算值?

不是。

我正在学习 Perl6 ...

1.3 这样的数字在数学和 Perl 6 中是小数。一些解释:

...来自 Perl5

这件事属于the Perl 5 to Perl 6 guide docs 之一。你愿意打开a new doc issue吗?

[1.0/15.0, 10.0/62.0],#this isn't evaluated

[1.0/10, 2/50.0],#neither is this

他们都被评估了。

在数学和 P6 中,文字 1.0 是小数是有理数。 foo / bar也是个理性人。

(好吧,如果foobar 都是整数或有理数并且结果的分母保持为64 位或更少,或者foobar 之一是任意精度FatRat理性。)

然而,Perl6 似乎并不喜欢我在这里指出的值。

你没有解释你看到的东西让你认为 P6 不喜欢它们的情况。

很有可能,根据Brad Gilbert++'s comment,您看到的值是&lt;1/15&gt;,而不是0.066667。前者是 100% 准确表示 1/15 的 P6 文字值。要 100% 准确地表示十进制显示必须是 0.06666666666666...,并在末尾加上 ... 或类似的名称,以表示无限重复的最终 6。但是&lt;1/15&gt; 表示相同的数字,而且更短,可以说更简单,所以dd.perl 使用&lt;1/15&gt; 形式代替。

当我声明二维数组时,如何让 Perl6 评估这样的表达式?

你不需要做任何事情。它正在评估它们。 :)

【讨论】:

  • 嗨@raiph,谢谢,我重新编辑了问题以解释这是for循环的一部分,它正在跳过子数组
  • 嗨@con。您当前的编辑无法编译。当我修复它进行编译时,包括用say 替换func,它可以工作......我建议你考虑休息一下,今天用P6 做其他事情,或者甚至在今天剩下的时间里跳过P6,然后返回明天用新的眼光来看待这个,因为那样你可能会立即明白这一切,就像这些事情经常发生的那样...... :)
【解决方案2】:

(这是一个nanswer,即本身不是答案。它最初是在@con 重写他们的问题以包含他们所有的代码之后编写的,并且是朝着我的Third and final answer 迈出的一步。现在希望它是一个有用的资源那些学习 Perl 6 的人。)

我对这个 nanswer 的第一次编辑的原始介绍

这是一大堆代码! :)

到目前为止,我的想法是:您是否绝对、肯定、100% 确定您没有错过一些输入数据?与 P6 相比,您跳过数据的可能性似乎要大得多,尤其是考虑到计算出的值正是您期望的下一个正确结果的值。

更新确实是问题出在输入数据不正确。)

相关代码的翻译和注释

此 nanswer 的其余部分是问题中代码的逐行“清理”(而不是重构)。我有两个目标,第二个是最重要的,亲爱的读者,请阅读以下内容:

  • 我的翻译有效地向我证明并向@con 证明我已经考虑了他们的每一点代码。这是为了减少错误可能在哪里的不确定性。请注意,我的大部分更改不可能与他们的错误直接相关,但在我完成重写之前,我并不愿意假设任何事情。

  • @con 的代码,以及我对它的翻译,可能对任何学习 Perl 6 的人都有用。 @con 的代码是 Perl 5 code 的 P6 翻译。 P5 代码又是C code 的翻译。还有将该代码翻译成其他语言的其他版本。我的代码采用@con 的翻译并将其翻译成更惯用的版本,并附有解释我为什么更改他们的代码的注释。

我对相关代码的翻译,可通过 tio 运行

My translation of @con's code, minus my commentary (see below), in tio.

(我最初的计划是,我们将基于修改 tio 中的代码并共享修改后的 tio 版本的链接来进一步探索 @con 的错误。为此,您/他们只需单击 tio 中的链接图标顶部 (?) 以在单击链接图标时获得指向代码的链接。Tio 非常适合编写、编辑和运行用 P6 和其他语言编写的代码,然后共享它。)

我对相关代码的翻译,带有注释

我保留了开头的lgamma 例程。我在脚注中写了很多关于它的评论,主要是为了其他读者,因为它包含大量有趣的功能1

sub lgamma ( Num(Real) \n --> Num ){
  use NativeCall;
  sub lgamma (num64 --> num64) is native {}
  lgamma( n )
}

我注意到lgamma 代码都是关于浮点数的(在 P6 中是 Num / num... 类型)。


sub pvalue (@a, @b) {

对于那些不了解 Perls 的人,sub 关键字引入了一个子例程(又名函数)。

这个有两个“listy”(Positional)参数。

(当您看到@(作为"sigil",例如@foo 或作为运算符,例如@($bar))时,请考虑“列表”。)


为了加快代码阅读速度并减少重复代码,我替换了这个:

  if @a.elems <= 1 {
    return 1.0;
  }
  if @b.elems <= 1 {
    return 1.0;
  }

用这个:

  return 1 if @a | @b <= 1;

用英文读作“如果列表@a 或列表@b 中的元素数小于或等于1,则返回1”。


我使用| 运算符构造了一个any junction

(不要浪费时间试图围绕结点的作用以及它们如何做的理论来思考。只需在实践中以简单和/或简洁的方式使用它们。如果它们保持简单,请阅读以一种简单的方式,它们很棒并且只是做显而易见的事情。如果在特定情况下使用它们会使代码不明显,那么请考虑针对该特定情况使用其他构造。)


数值上下文中的数组计算其元素数。像&lt;= 这样的数字运算符强加了数字上下文。所以我放弃了.elems

数字上下文和在数字上下文中计算其长度的数组是 P6 的基本方面,因此这是一种惯用编码,适用于除最基本的介绍性新手示例之外的所有示例。


我从1.0 切换到1

我的猜测是@con 写了1.0,因为这就是在他们正在翻译的代码中的字面意义和/或它表示浮点值的意图。但是在 P6 普通十进制文字(没有 e 指数)中,比如 1.0 会产生有理数。

在这段代码中使用1.0 代替1 将更简单的快速类型(整数)替换为更复杂的慢速类型(有理数)。当在 any 组件值是浮点数的公式中使用时,这种较慢类型的值将被强制转换为浮点数(比整数更慢)。此代码中的大多数或所有公式都会发生这种情况,因为lgamma 返回一个浮点数。

更一般地说,如果您保留变量和值的类型未指定,P6 的工作和阅读效果最好,让编译器自行确定,除非有令人信服的理由来指定它们。不指定类型可以减少读者的认知负担,并增加代码重用和编译器优化代码的灵活性。

这导致了一对互补的格言:

  • 默认情况下,保留类型信息隐式。如果您不知道给定值或变量的类型是否重要,或者知道这无关紧要,请不要指定它。

  • 如果您使值、变量或参数的类型显式,那么 P6 将使用该类型强制遵守该类型,无论是否改进您的代码或不必要地减慢代码速度或完全停止它。

如果您绝对知道需要使用不同的类型或添加类型约束以使代码正确,那么请务必继续。同样,如果您已经验证您的代码是正确的 没有更具体的类型,但您想让它更快、更安全或更清晰,请继续。但是,如果您知道,那就让它通用吧。正如 Ben 曾经说过的那样,P6 的设计初衷就是按照您的意思行事,并且会比您想象的更频繁地取得成功。

为了更加有力地说明这一点,类似于 P6 中的premature optimization,一次性代码和长期生产代码中的premature typing is an anti-pattern


  my Rat $mean1 = @a.sum / @a.elems;
  my Rat $mean2 = @b.sum / @b.elems;
  if $mean1 == $mean2 {
    return 1.0;
  }

成为:

  my (\mean_a, \mean_b) = @a.sum / @a, @b.sum / @b;
  return 1 if mean_a == mean_b;

除非我知道我需要一个印记,否则我通常会“削减”“变量”的印记。如果“变量”实际上没有变化,它可能不需要印记。

我已将$mean1 重命名为mean_a,因为它明显对应于@a


  my Rat $variance1 = 0.0;
  my Rat $variance2 = 0.0;

  for @a -> $i {
    $variance1 += ($mean1 - $i)**2#";" unnecessary for last statement in block
  }
  for @b -> $i {
    $variance2 += ($mean2 - $i)**2
  }

成为:

  my ($vari_a, $vari_b);

  $vari_a += (mean_a - $_)² for @a;
  $vari_b += (mean_b - $_)² for @b;

将变量$_读作“它”。


  if ($variance1 == 0 && $variance2 == 0) {
    return 1.0;
  }
  $variance1 /= (@a.elems - 1);
  $variance2 /= (@b.elems - 1);

成为:

  return 1 unless ($vari_a or $vari_b);

  $vari_a /= (@a - 1);
  $vari_b /= (@b - 1);

在 Perls 中,0 在布尔测试上下文中计算为 False。而像 @a 这样的数组或列表会在数值上下文中计算其元素数。


  my $WELCH_T_STATISTIC = ($mean1-$mean2)/sqrt($variance1/@a.elems+$variance2/@b.elems);
  my $DEGREES_OF_FREEDOM = (($variance1/@a.elems+$variance2/@b.elems)**2)
  /
  (
  ($variance1*$variance1)/(@a.elems*@a.elems*(@a.elems-1))+
  ($variance2*$variance2)/(@b.elems*@b.elems*(@b.elems-1))
  );
  my $A = $DEGREES_OF_FREEDOM/2;
  my $value = $DEGREES_OF_FREEDOM/($WELCH_T_STATISTIC*$WELCH_T_STATISTIC+$DEGREES_OF_FREEDOM);
  my Num $beta = lgamma($A)+0.57236494292470009-lgamma($A+0.5);
  my Rat $acu = 10**(-15);
  my ($ai,$cx,$indx,$ns,$pp,$psq,$qq,$rx,$temp,$term,$xx);
  # Check the input arguments.
  return $value if $A <= 0.0;# || $q <= 0.0;

成为:

  my \WELCH_T_STATISTIC  = (mean_a - mean_b)
                / ( $vari_a / @a   +   $vari_b / @b ).sqrt;

  my \DEGREES_OF_FREEDOM = ($vari_a / @a   +   $vari_b / @b)²
          / ($vari_a² / (@a² * (@a - 1))   +   $vari_b² / (@b² * (@b - 1)));

  my \A                  = DEGREES_OF_FREEDOM / 2;
  my $value              = DEGREES_OF_FREEDOM
             / (WELCH_T_STATISTIC² + DEGREES_OF_FREEDOM);

  my \magic-num          = 0.57236494292470009;
  my \beta               = lgamma(A) + magic-num - lgamma(A + 0.5);
  my \acu                = 1e-15;

  # Check the input arguments.
  return $value if A <= 0;# || $q <= 0.0;

(上一行中的$q 是什么意思?)

请注意,我删除了 betaacu 上的类型。分配给beta变量无论如何都会是Num,因为lgamma返回一个Num。分配给acu 的值也将是Num,因为在数字文字中使用e 指数意味着它构造的值是Num


  return $value if $value < 0.0 || 1.0 < $value;
  # Special cases
  return $value if $value == 0.0 || $value == 1.0;

成为:

  return $value unless $value ~~ 0^..^1;

0^ 读作“大于零”(不包括零),将^1 读作“最多一”(不包括一)。

~~ 是“智能匹配”运算符。如果右边的值接受左边的值,则返回True

因此,如果$value 小于或等于0 或大于或等于1,则此返回语句返回$value


作为一个小整理,我将在上述重写中删除的大量变量的 my 声明移动到此时,就在它们变得相关之前,并添加了 $ns

  my ($ai, $cx, $indx, $pp, $psq, $qq, $rx, $temp, $term, $xx, $ns);

  $psq = $A + 0.5;
  $cx = 1.0 - $value;
  if $A < $psq * $value {
      ($xx, $cx, $pp, $qq, $indx) = ($cx, $value, 0.5, $A, 1);
  } else {
      ($xx, $pp, $qq, $indx) = ($value, $A, 0.5, 0);
  }

成为:

  $psq = A + 0.5;
  $cx = 1 - $value;
  ($xx, $cx, $pp, $qq, $indx) =
        A < $psq * $value
          ?? ($cx, $value, 0.5, A, 1)
          !! ($value, $cx, A, 0.5, 0);

我将一堆变量的条件赋值重写为ternary,这样更容易看到分配给了什么。


  $term = 1.0;
  $ai = 1.0;
  $value = 1.0;
  $ns = $qq + $cx * $psq;
  $ns = $ns.Int;

成为:

  $term = 1;
  $ai = 1;
  $value = 1;
  $ns = ($qq + $cx * $psq) .Int;

1.0s 替换为1s 并将分配给$ns 的表达式与.Int 强制结合起来。

(我在翻译时从代码中剥离了类型,它继续计算正确的结果,除了删除上面的Int 强制使代码无限循环。这就是最终导致我搜索网络以查看是否可以的原因发现 @con 正在翻译的代码。那时我在 rosettacode.org 上找到了它。在我看到的代码中,它被显式输入为整数,所以大概它是确保算法正常工作的核心。)


  #Soper reduction formula.
  $rx = $xx / $cx;
  $temp = $qq - $ai;
  $rx = $xx if $ns == 0;

(没有改变。)


  while (True) {

成为:

  loop {

    $term = $term * $temp * $rx / ( $pp + $ai );
    $value = $value + $term;
    $temp = $term.abs;

(没有改变。)


    if $temp <= $acu && $temp <= $acu * $value {
      $value = $value * ($pp * $xx.log + ($qq - 1.0) * $cx.log - $beta).exp / $pp;
      $value = 1.0 - $value if $indx;
      last;
    }

成为:

    if $temp <= acu & acu * $value {
      $value = $value * ($pp * $xx.log + ($qq - 1) * $cx.log - beta).exp / $pp;
      $value = 1 - $value if $indx;
      last;
    }

这次包含结点 (&amp;) 的条件用英文读作“如果 temp 小于或等于 acu 和 acu 乘以值”。


    $ai++;
    $ns--;
    if 0 <= $ns {
        $temp = $qq - $ai;
        $rx = $xx if $ns == 0;
    } else {
        $temp = $psq;
        $psq = $psq + 1;
    }
  }
  return $value;
}

我刚刚将1.0 替换为1


现在是有问题的数组。正如我在开头所写的那样,我很确定您(或您的数据提供者)刚刚忘记了几行:

my @array2d =

  [27.5,21.0,19.0,23.6,17.0,17.9,16.9,20.1,21.9,22.6,23.1,19.6,19.0,21.7,21.4],
  [27.1,22.0,20.8,23.4,23.4,23.5,25.8,22.0,24.8,20.2,21.9,22.1,22.9,20.5,24.4],

  [17.2,20.9,22.6,18.1,21.7,21.4,23.5,24.2,14.7,21.8],
  [21.5,22.8,21.0,23.0,21.6,23.6,22.5,20.7,23.4,21.8,20.7,21.7,21.5,22.5,23.6,21.5,22.5,23.5,21.5,21.8],

  [19.8,20.4,19.6,17.8,18.5,18.9,18.3,18.9,19.5,22.0],
  [28.2,26.6,20.1,23.3,25.2,22.1,17.7,27.6,20.6,13.7,23.2,17.5,20.6,18.0,23.9,21.6,24.3,20.4,24.0,13.2],

  [30.02,29.99,30.11,29.97,30.01,29.99],
  [29.89,29.93,29.72,29.98,30.02,29.98],

  [3.0,4.0,1.0,2.1],
  [490.2,340.0,433.9],

  [<1.0/15.0>, <10.0/62.0>],
  [<1.0/10>, <2/50.0>],

  [0.010268,0.000167,0.000167],
  [0.159258,0.136278,0.122389],

  [9/23.0,21/45.0,0/38.0],
  [0/44.0,42/94.0,0/22.0];

say @array2d[11][0];

谁或什么说这些是正确的答案?您是否 100% 确定 0.0033... 答案与 [&lt;1.0/15.0&gt;, &lt;10.0/62.0&gt;],[&lt;1.0/10&gt;, &lt;2/50.0&gt;] 数据一致?

my @CORRECT_ANSWERS =
      0.021378001462867,
      0.148841696605327,
      0.0359722710297968,
      0.090773324285671,
      0.0107515611497845,
      0.00339907162713746,
      0.52726574965384,
      0.545266866977794;

在最后一点,我刚刚删除了类型,并再次使用上标作为更漂亮的值加指数 (10⁻⁹):

my $i = 0;
my $error = 0;
for @array2d -> @left, @right {
  my $pvalue = pvalue(@left, @right);
  $error += ($pvalue - @CORRECT_ANSWERS[$i]).abs;
  say "$i [" ~ @left.join(',') ~ '] [' ~ @right ~ "] = $pvalue";
  if $error > 10⁻⁹ {
    say "\$p = $pvalue, but should be @CORRECT_ANSWERS[$i]";
    die;
  }
  #  printf("Test sets %u p-value = %.14g\n",$i+1,$pvalue);
  $i++
}

printf("the cumulative error is %g\n", $error);

脚注

1 喜欢lgamma 的好习惯! (原来是Brad Gilbert wrote it。)

sub lgamma ( Num(Real) \n --> Num ){
  use NativeCall;
  sub lgamma (num64 --> num64) is native {}
  lgamma( n )
}

展示:

  • 用同名的高级 P6 (Perl 6) 例程对低级 (C) 例程进行阴影处理,以便在调用 C 函数之前添加进一步处理。

  • Explicitly converting the input type 从较宽的 P6 类型 Real 数字到较窄的 Num。根据该术语的原始技术定义,Perls 是 "strongly typed",但 P6 为每个 other interpretations of "strong typing" 提供了额外的选项,并且相对于不能对“强类型”进行这些其他解释的语言(如 Perl 5 、Python 和 C)。显式类型转换是 P6 引入的这种能力转变的一部分。

  • 削减印记。这将在我在本文其他地方做同样的事情的地方进一步讨论。

  • 对库的 use 进行词法范围界定。内部 lgamma 例程和由 use Nativecall; 导入的符号在包含它的外部 lgamma 例程中不可见。

  • 使用 NativeCall(P6 C FFI)允许高级 P6 代码直接映射到 C 代码,包括从 P6 的 IEEE 双浮点兼容 boxed type Num 自动转换为未装箱的 @ 987654341@ 相当于num64

全部在 5 行!非常好。 :)

【讨论】:

  • 我无法提供链接,但我是写lgamma sub的人。
  • 我以为是在 irc 或 gist 或其他地方。老实说,我没想到这里。
【解决方案3】:

第三个也是最后一个答案

.oO(他说,希望如此。有没有人写过四个对 SO 问题的答案?!??)

如果您在数据中交换这些行:

  [<1.0/15.0>, <10.0/62.0>],
  [<1.0/10>, <2/50.0>],

  [0.010268,0.000167,0.000167],
  [0.159258,0.136278,0.122389],

相反:

  [0.010268,0.000167,0.000167],
  [0.159258,0.136278,0.122389],

  [<1.0/15.0>, <10.0/62.0>],
  [<1.0/10>, <2/50.0>],

那么你的程序的输出(至少是我重写你的代码 nanswer 的版本)是:

0.159258
0 [27.5,21,19,23.6,17,17.9,16.9,20.1,21.9,22.6,23.1,19.6,19,21.7,21.4] [27.1 22 20.8 23.4 23.4 23.5 25.8 22 24.8 20.2 21.9 22.1 22.9 20.5 24.4] = 0.02137800146286709
1 [17.2,20.9,22.6,18.1,21.7,21.4,23.5,24.2,14.7,21.8] [21.5 22.8 21 23 21.6 23.6 22.5 20.7 23.4 21.8 20.7 21.7 21.5 22.5 23.6 21.5 22.5 23.5 21.5 21.8] = 0.14884169660532756
2 [19.8,20.4,19.6,17.8,18.5,18.9,18.3,18.9,19.5,22] [28.2 26.6 20.1 23.3 25.2 22.1 17.7 27.6 20.6 13.7 23.2 17.5 20.6 18 23.9 21.6 24.3 20.4 24 13.2] = 0.035972271029797116
3 [30.02,29.99,30.11,29.97,30.01,29.99] [29.89 29.93 29.72 29.98 30.02 29.98] = 0.09077332428566681
4 [3,4,1,2.1] [490.2 340 433.9] = 0.010751561149784494
5 [0.010268,0.000167,0.000167] [0.159258 0.136278 0.122389] = 0.003399071627137453
6 [1.0/15.0,10.0/62.0] [1.0/10 2/50.0] = 0.5272657496538401
7 [0.391304,0.466667,0] [0 0.446809 0] = 0.5452668669777938
the cumulative error is 5.50254e-15

回想起来,这很明显是错误的。 2020 年的事后诸葛亮。 :)

【讨论】:

  • "虽然通常会回避“谢谢”cmets,但您的非凡耐心值得例外,感谢您的耐心@raiph
猜你喜欢
  • 1970-01-01
  • 2020-10-14
  • 1970-01-01
  • 2019-12-15
  • 2019-05-18
  • 1970-01-01
  • 1970-01-01
  • 2019-03-19
  • 1970-01-01
相关资源
最近更新 更多