He escrito un script de Raku para llamar a la función erf
en la biblioteca estándar de C:
use NativeCall; sub erf(num64) returns num64 is native { * }; say [0.5,1,2,3,4,-0.9].map: {erf($_.Num)};
La salida de este script
(0.5204998778130465 0.8427007929497149 0.9953222650189527 0.9999779095030014 0.9999999845827421 -0.7969082124228322)
coincide con la salida de C para todos los valores [0.5,1,2,3,4,-0.9]
excepto 4
.
Para 4
, C genera 1.000000
mientras que Raku da 0.9999999845827421
.
Para probar la salida de 4
en C, ejecute este código:
#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; }
¿Tienes idea de lo que está pasando? También necesito generar 1.0
desde Raku.
Para el código C, cambie %f
a %.99g
para mostrar más dígitos. Esto revela erf(4)
devuelve 0.9999999845827420852373279558378271758556365966796875.
%f
solicita seis dígitos después del punto decimal. El valor se redondea para ajustarse a ese formato. %. number f
solicita dígitos number
después del punto decimal y siempre usa el formato "fijo". %. number g
solicita number
significativos y utiliza un formato "general" que cambia a notación exponencial cuando corresponde.
Para el código Raku, si desea una salida de "1.0" o "1.000000", deberá aplicar alguna solicitud de formato a la salida. No practico Raku, pero una breve búsqueda muestra que Raku tiene características similares a printf
que puede usar, por lo que solicitar el formato %f
debería duplicar la salida C.
Otra versión más que se basa en la explicación de @Eric sobre la precisión:
my $fmt = '%.6f'; printf [$fmt ~ ' '] x 5 ~ $fmt ~ "\n", [0.5,1,2,3,4,-0.9].map: {erf($_.Num)};
[$fmt ~ ' '] x 5 ~ $fmt ~ "\n"
genera la cadena de formato "%.6f %.6f %.6f %.6f %.6f %.6f\n"
Producción
0.520500 0.842701 0.995322 0.999978 1.000000 -0.796908
O incluso más raku como lo propone raiph , usando el operador infijo xx
:
printf "{'%.6f' xx 6} \n", [0.5,1,2,3,4,-0.9].map: {erf($_.Num)};
Estás comparando manzanas con naranjas.
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
Está usando printf
en C, si usa .fmt
(la forma más fácil de decir sprintf
en Raku), entonces también obtendrá 1.0
.