使用 NativeCall 调用 C fn `erf` 比 C 中的 `erf` 获得更精确的输出

Sum*_*nal 11 c printf rakudo nativecall raku

我编写了一个 Raku 脚本来调用erfC 标准库中的函数:

use NativeCall;
sub erf(num64) returns num64 is native { * };

say [0.5,1,2,3,4,-0.9].map: {erf($_.Num)};
Run Code Online (Sandbox Code Playgroud)

该脚本的输出

(0.5204998778130465 0.8427007929497149 0.9953222650189527 0.9999779095030014 0.9999999845827421 -0.7969082124228322)
Run Code Online (Sandbox Code Playgroud)

[0.5,1,2,3,4,-0.9]除 之外的所有值都与 C 的输出匹配4

对于4C 输出,1.000000而 Raku 给出0.9999999845827421

要测试 C 语言的输出4,请运行以下代码:

#include <stdio.h> // Including header file for printf function
#include <math.h>  // Including header file for erf function

int main (){

  double param, result;
  param = 4.0;
  result = erf(param);
  printf("erf (%f) = %f\n", param, result);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

知道发生了什么事吗?我也需要1.0从 Raku 输出。

Eri*_*hil 9

对于 C 代码,更改%f%.99g以显示更多数字。这显示erf(4)返回 0.9999999845827420852373279558378271758556365966796875。

\n

%f要求小数点后六位数字。该值将被四舍五入以适合该格式。请求小数点后的数字,并始终使用 \xe2\x80\x9cfixed\xe2\x80\x9d 格式。请求有效数字并使用 aa \xe2\x80\x9cgeneral\xe2\x80\x9d 格式,在适当的时候切换到指数表示法。%.numberfnumber%.numbergnumber

\n

对于 Raku 代码,如果您想要输出 \xe2\x80\x9c1.0\xe2\x80\x9d 或 \xe2\x80\x9c1.000000\xe2\x80\x9d,则需要向输出。我不练习 Raku,但简短的搜索显示 Raku 具有printf您可以使用的类似功能,因此请求%f它的格式应该会重复 C 输出。

\n


Ted*_*gmo 7

另一个版本建立在 @Eric 关于精度的解释之上:

my $fmt = '%.6f';
printf [$fmt ~ ' '] x 5 ~ $fmt ~ "\n", [0.5,1,2,3,4,-0.9].map: {erf($_.Num)};
Run Code Online (Sandbox Code Playgroud)

[$fmt ~ ' '] x 5 ~ $fmt ~ "\n"构建格式字符串"%.6f %.6f %.6f %.6f %.6f %.6f\n"

输出

0.520500 0.842701 0.995322 0.999978 1.000000 -0.796908
Run Code Online (Sandbox Code Playgroud)

或者甚至更多raiph提出的,使用中运算符xx

printf "{'%.6f' xx 6} \n", [0.5,1,2,3,4,-0.9].map: {erf($_.Num)};
Run Code Online (Sandbox Code Playgroud)

  • 很好的后续。仅供参考 `$fmt xx 6 ~ "\n"` 构建相同的格式字符串。请参阅 [`xx`](https://docs.raku.org/routine/xx) 和 [`List.Str`](https://docs.raku.org/type/List#method_Str)。同样`"{$fmt xx 6} \n"`。请参阅[“使用大括号从字符串内插入 Raku 代码:”](https://docs.raku.org/language/quoting#Interpolation:_qq#:~:text=interpolate%20Raku%20code%20from%20within %20the%20string,%20using%20curly%20braces)。 (2认同)

Eli*_*sen 6

您正在将苹果与橙子进行比较。

use NativeCall;
sub erf(num64) returns num64 is native { * };

say .fmt("%f") for [0.5,1,2,3,4,-0.9].map: {erf($_.Num)}

0.520500
0.842701
0.995322
0.999978
1.000000
-0.796908
Run Code Online (Sandbox Code Playgroud)

printf在 C 中使用,如果你使用.fmt(在 Raku 中更简单的说法sprintf),那么你也会得到1.0.