具有一定精度的逐元素比较

Sum*_*nal 7 rakudo raku

我正在寻找带有预期输出数组的函数(返回array )的测试输出 )的测试输出。

例子:

use Test;
sub myoutput($n) {
    (1..$n)>>.sqrt
}

is myoutput(3), (1, 1.4142135623730951, 1.7320508075688772);
Run Code Online (Sandbox Code Playgroud)

这看起来不错,但我想将精度设置为1e-12.

我得出的是这样的:

sub element_wise_testing_with_precision(@functionoutput, @expectedoutput, $precision) {
    die "Provide equal elements!" if +@functionoutput != +@expectedoutput;
    loop (my $i = 0; $i < +@functionoutput; $i++)  {
        is-approx @functionoutput[$i], @expectedoutput[$i], $precision;
    }
}


my @expected = (1, 1.4142135623730951, 1.7320508075688772);
element_wise_testing_with_precision(myoutput(3), @expected, 1e-12)

Run Code Online (Sandbox Code Playgroud)

有效(!)但不确定这是否是正确的方法。是否有使用Z 运算符Hyper 运算符执行此操作的方法,因为它们似乎执行按元素运算?

cod*_*ons 8

您对 hyper 和 zip/Z 运算符的直觉是完全正确的:可以使用它们中的任何一个执行您想要的操作。这个难题中缺少的一部分是部分应用(Raku 通常称之为启动)。Raku 提供了两种启动 \xe2\x80\x93 的方法,即部分应用 \xe2\x80\x93 函数:方法.assuming(启动子程序)和Whatever-priming(启动运算符或方法)。

\n

由于&is-approx是一个子程序,&assuming因此是我们所追求的启动方法。要将精度指定为第三个参数,我们将编写&is-approx.assuming(*, *, $precision)。或者,由于&is-approx允许使用命名参数指定精度,因此我们可以将其简化为&is-approx.assuming: :abs-tol($precision)

\n

完成此操作后,我们可以使用hyper或 Z 元运算符来应用我们的新函数元素。请注意,因为元运算符需要中缀运算符,所以我们需要通过将函数括在方括号中来使用函数的中缀形式。

\n

这是经过最小更改的代码:

\n
sub element_wise_testing_with_precision(@functionoutput, @expectedoutput, $precision) {\n    die "Provide equal elements!" if +@functionoutput != +@expectedoutput;\n\n    my &close-enough = &is-approx.assuming(*,*, $precision);\n    @functionoutput \xc2\xab[&close-enough]\xc2\xbb @expectedoutput\n\n  # or this also works:\n  # @functionoutput Z[&close-enough] @expectedoutput\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是一个带有一些切线更改的版本,以使其更加惯用:

\n
sub element-wise-is-approx(@got, @expected, $abs-tol) {\n    PRE { +@got == +@expected }\n\n    my &close-enough = &is-approx.assuming: :$abs-tol;\n    @got \xc2\xab[&close-enough]\xc2\xbb @expected\n}\n\nelement-wise-is-approx(myoutput(3), @expected, 1e-12);\n
Run Code Online (Sandbox Code Playgroud)\n

事实上,我们甚至可以内联执行此操作,如下所示。在这里,我们切换到 hyper ( ) 的非 DWIM 版本\xc2\xbb \xc2\xab,以强制执行大小相等的参数。

\n
myoutput(3) \xc2\xbb[&(&is-approx.assuming(*,*,1e-12))]\xc2\xab @expected\n
Run Code Online (Sandbox Code Playgroud)\n

&( )(请注意,需要中缀运算符中的额外in 来向 Raku 编译器阐明我们的意图。)

\n