A value not really zero, but close enough. Bug or feature?

Hi all,
I have a problem with, I think, passing small values from ROOT functions to Python. I have some code which runs a TH1.KolmogorovTest.
In a few cases the probability is so low that Python returns 0.00, but the value from c++ is not zero itself, as running the test with the “D” debug option shows:

Kolmo Prob = 1.4241e-22, Max Dist = 0.0506582
kolm prob from python 0.0

I find this quite annoying, but it could be a feature, since I read in the documentation of TMath.KolmogorovProb that:

Accuracy: The function is far too accurate for any imaginable application.
Probabilities less than 10^-15 are returned as zero.

Is there any workaround? Is it really a feature?
Thanks for your help.


could you provide a code snippet that exhibits the problem? The representation of a double in python is simply a python object with a pay-load that is a C double (there is no float in python: a python float is a C double), so I’m hard-pressed to believe that there would be any difference resulting from the interface.


Aha, I found the culprit. It’s not really the KolmogorovTest function, but the TMath::ErfInverse I use to calculate the confidence level afterwards.

If the p-value is too small (around 1e-17) ErfInverse(1 - p) returns 0.
I think the algorithm does not converge for such extreme values. The code says:

[code]Double_t TMath::ErfInverse(Double_t x)
// returns the inverse error function
// x must be <-1<x<1

Int_t kMaxit = 50;
Double_t kEps = 1e-14;
Double_t kConst = 0.8862269254527579; // sqrt(pi)/2.0

if(TMath::Abs(x) <= kEps) return kConst*x;

// Newton iterations
Double_t erfi, derfi, y0,y1,dy0,dy1;
if(TMath::Abs(x) < 1.0) {
erfi = kConstTMath::Abs(x);
y0 = TMath::Erf(0.9
derfi = 0.1*erfi;
for (Int_t iter=0; iter<kMaxit; iter++) {
y1 = 1. - TMath::Erfc(erfi);
dy1 = TMath::Abs(x) - y1;
if (TMath::Abs(dy1) < kEps) {if (x < 0) return -erfi; else return erfi;}
dy0 = y1 - y0;
derfi *= dy1/dy0;
y0 = y1;
erfi += derfi;
if(TMath::Abs(derfi/erfi) < kEps) {if (x < 0) return -erfi; else return erfi;}
return 0; //did not converge

so Python is not really involved here, but this still leaves me with ugly graphs…