Search code examples
cprintfrakurakudonativecall

Using NativeCall to call the C fn `erf` gets more precise output than `erf` in C


I have written a Raku script to call erf function in C standard library:

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

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

The output of this script

(0.5204998778130465 0.8427007929497149 0.9953222650189527 0.9999779095030014 0.9999999845827421 -0.7969082124228322)

matches with the output from C for all values [0.5,1,2,3,4,-0.9] except 4.

For 4 the C outputs 1.000000 while Raku gives 0.9999999845827421.

To test the output for 4 in C, run this code:

#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;
}

Any idea what's going on? I need to output 1.0 from Raku too.


Solution

  • You're comparing apples with oranges.

    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
    

    You're using printf in C, if you use .fmt (the easier way to say sprintf in Raku), then you'd also get 1.0.