protected double invCdfRootFinding ( double p , double tol ) { if ( p < 0 || p > 1 ) throw new ArithmeticException ( "Value of p must be in the range [0,1], not " + p ) ; //two special case checks, as they can cause a failure to get a positive and negative value on the ends, which means we can't do a search for the root //Special case check, p < min value if ( min ( ) >= Integer . MIN_VALUE ) if ( p <= cdf ( min ( ) ) ) return min ( ) ; //special case check, p >= max value if ( max ( ) < Integer . MAX_VALUE ) if ( p > cdf ( max ( ) - 1 ) ) return max ( ) ; //stewpwise nature fo discrete can cause problems for search, so we will use a smoothed cdf to pass in // double toRet= invCdf(p, ); //Lets use an interpolated version of the CDF so that our numerical methods will behave better Function1D cdfInterpolated = ( double x ) -> { double query = x ; //if it happens to fall on an int we just compute the regular value if ( Math . rint ( query ) == query ) return cdf ( ( int ) query ) - p ; //else, interpolate double larger = query + 1 ; double diff = larger - query ; return cdf ( query ) * diff + cdf ( larger ) * ( 1 - diff ) - p ; } ; double a = Double . isInfinite ( min ( ) ) ? Integer . MIN_VALUE * .95 : min ( ) ; double b = Double . isInfinite ( max ( ) ) ? Integer . MAX_VALUE * .95 : max ( ) ; double toRet = Zeroin . root ( tol , a , b , cdfInterpolated ) ; return Math . round ( toRet ) ; }
Helper method that computes the inverse CDF by performing root - finding on the CDF of the function . This provides a convenient default method for any invCdfRootFinding implementation but may not be as fast or accurate as possible .