I writing a program in Java which requires me to compute some probabilities, and for larger inputs, the probabilities can eventually become very small. Therefore, to prevent underflow issues, I would like to take the log probabilities instead.
I am, however, having trouble implementing this. At each stage of computation there can be a different number of options, to which probabilities need to be assigned, and each stage they need to add up to 1. The probabilities are based on a number of different variables. I take a sum over all possibilities using the following formula:
Math.pow(d[i], a) * Math.pow(1/c[i], b)
This gives me a variable, total. To then establish the probability p_i,
p_i = (Math.pow(d[i], a) * Math.pow(1/c[i], b)) / total
My question is, how can I implement this using log probabilities, so that I do not get 'Infinity' and 'NaN' values, since these are what I have been getting so far.
What I think you should try is to use Kahan Summation. It will allow to sum properly not loosing precision.
In some C-like pseudo-code (sorry, my Java is rusty, code is untested)
double total(int N, double[] d, double[] c, double a, double b) {
double sum = 0.0;
double running_error = 0.0;
for (int i = 0; i != N; ++i) {
if (d[i] == 0.0)
continue;
if (c[i] == 0.0)
throw "XXX"; // some error reporting
double v = 0.0;
if (d[i] > 0.0 && c[i] > 0.0) {
// using log trick, if you want
double lpi = a*Math.log(d[i]) - b*Math.log(c[i]);
v = Math.exp(lpi);
}
else {
v = Math.pow(d[i], a) * Math.pow(1.0/c[i], b);
}
double difference = v - running_error;
double temp = sum + difference;
running_error = (temp - sum) - difference;
sum = temp;
}
return sum;
}
Related
I was trying to create a program that finds the power of a real number . The problem is that exponent is in decimal and less than 1 but not negative.
suppose we have to find the power of
50.76
what i really tried was i wrote 0.76 as 76/100 and it would be 576/100
and after that i wrote
here is the code if you want to see what i did
public class Struct23 {
public static void main(String[] args) {
double x = 45;
int c=0;
StringBuffer y =new StringBuffer("0.23");
//checking whether the number is valid or not
for(int i =0;i<y.length();i++){
String subs = y.substring(i,i+1);
if(subs.equals(".")){
c=c+1;
}
}
if(c>1){
System.out.println("the input is wrong");
}
else{
String nep= y.delete(0, 2).toString();
double store = Double.parseDouble(nep);
int length = nep.length();
double rootnum = Math.pow(10, length);
double skit = power(x,store,rootnum);
System.out.println(skit);
}
}
static double power(double x,double store,double rootnum){
//to find the nth root of number
double number = Math.pow(x, 1/rootnum);
double power = Math.pow(number, store);
return power;
}
}
the answer would come but the main problem is that i cannot use pow function to do that
i can't also use exp() and log() functions.
i can only use
+
-
*
/
help me suggest your ideas .
thanks in advance
def newtons_sqrt(initial_guess, x, threshold=0.0001):
guess = initial_guess
new_guess = (guess+float(x)/guess)/2
while abs(guess-new_guess) > threshold :
guess=new_guess
new_guess = (guess+float(x)/guess)/2
return new_guess
def power(base, exp,threshold=0.00001):
if(exp >= 1): # first go fast!
temp = power(base, exp / 2);
return temp * temp
else: # now deal with the fractional part
low = 0
high = 1.0
sqr = newtons_sqrt(base/2,base)
acc = sqr
mid = high / 2
while(abs(mid - exp) > threshold):
sqr = newtons_sqrt(sqr/2.0,sqr)
if (mid <= exp):
low = mid
acc *= sqr
else:
high = mid
acc *= (1/sqr)
mid = (low + high) / 2;
return acc
print newtons_sqrt(1,8)
print 8**0.5
print power(5,0.76)
print 5**0.76
I reapropriated most of this answer from https://stackoverflow.com/a/7710097/541038
you could also expound on newtons_sqrt to give newtons_nth_root ... but then you have to figure out that 0.76 == 76/100 (which im sure isnt too hard really)
you can convert your number to complex form of it and then use de Moivre' formula to compute the nth root of your number using your legal oprations.
Background: I have the following code which calculates the Gaussian Function as a sum of an infinite series.
The Gaussian Function, at it's simplest form is e^-(x^2).
This can be calculated as the sum of an infinite series, using the Taylor Series expansion.
Therefore, e^-(x^2) = 1 - (x^2) + (x^4)/2! - (x^6)/3! ....
public static double expSeries (double x, int n){
double result = 0.0, x0 = 1.0, x1;
result+= x0;
for (int i=1; i<=n; i++){
x1 = x0 * ((x*x)/i);
if (i%2 == 0){
result += x1;
} else {
result -= x1;
}
x0 = x1;
}
return result;
}
As a comparison, I use Math.exp(-(x*x)) to see if my function works correctly.
The function seems to work for low values of x, but behaves inconsistently after that. Here are the output of a few test cases:
x=1; n=10
Result : 0.3678794642857144
Math.exp: 0.36787944117144233
x=1; n=100
Result : 0.36787944117144245
Math.exp: 0.36787944117144233
x=2; n=100
Result : 0.018315638888733953
Math.exp: 0.01831563888873418
x=3; n=100
Result : 1.234098038990534E-4
Math.exp: 1.2340980408667956E-4
x=4; n=100
Result : 1.1247503313371918E-7
Math.exp: 1.1253517471925912E-7
x=5; n=100
Result : 8.181278981021932E-7
Math.exp: 1.3887943864964021E-11
x=6; n=100
Result : -0.03197975209642004
Math.exp: 2.319522830243569E-16
x=7; n=100
Result : 3.6698962220692825E10
Math.exp: 5.242885663363464E-22
What am I missing here?
Your algorithm looks fine and you are probably hitting the limits of double precision.
I would suggest to rewrite the algo for the Taylor series of exp(x) instead of exp(-x2), which is a little more straightforward to code:
public static double expSeries(double x, int n) {
double term = 1;
double result = term;
for (int i = 1; i <= n; i++) {
term *= x / i;
result += term;
}
return result;
}
You can then add an expSeries_X2(x, i) { return expSeries(-x*x, i); } if you want.
We can then rewrite that method using BigDecimals:
public static double expSeries(double x, int n) {
BigDecimal result = ONE;
BigDecimal term = ONE;
BigDecimal x_ = new BigDecimal(x);
for (int i = 1; i <= n; i++) {
term = term.multiply(x_.divide(BigDecimal.valueOf(i), MathContext.DECIMAL128));
result = result.add(term);
}
return result.doubleValue();
}
And it should return a result that is closer to what you expect.
This is a great lesson in problems with floating point numbers.
Taylor series is not always a good way to calculate a function value.
Look at the general definition here. You're calculating the value of the function by extrapolating out from a certain point a. In your case, that value is zero, so exp(0) = 1. The further you go from zero, the worse the extrapolation. So it is with all extrapolations, regardless of how you do it.
Even worse, you're depending on alternating signs of very large numbers to cancel each other out and give you something sensible. If x = 7 and e = 2.71...., how large a number is 2^49 or 3^49? Very large, indeed.
I don't think the answer should be BigDecimal. A better idea would be to understand exactly what you're doing and find out if there are better ways to approximate the function for large exponents.
Gaussian is used in statistics to model the normal distribution. If you normalize the function parameter to the Z-score (Z = (x-xmean)/stddev) you'll see that 99.9% of the area under the function falls in the range -3 <= Z <= +3 (plus or minus three standard deviations). You aren't likely to need parameter that falls outside that range.
I have rewriten the formula with BigDecimal:
public static void main(String... args){
for(int i=1;i < 8; ++i){
double l = Math.exp(-(Math.pow(i, 2)));
double r = expSeries(BigDecimal.valueOf(i), 100);
System.out.println( l + " - " + r + " = " + (l - r) );
}
}
public static double expSeries (BigDecimal x, int n){
BigDecimal result = BigDecimal.ONE, x1;
for (int i=1; i<=n; i++){
x1 = x.pow(i*2).divide(new BigDecimal(factorial(BigInteger.valueOf(i))), MathContext.DECIMAL128);
if (i%2 == 0) {
result = result.add(x1);
}
else{
result = result.subtract(x1);
}
}
return result.doubleValue();
}
public static BigInteger factorial (BigInteger num){
if (num.compareTo(BigInteger.ONE) == 0) return num;
return num.multiply(
factorial(num.subtract(BigInteger.ONE)));
}
And the result :
0.36787944117144233 - 0.36787944117144233 = 0.0
0.01831563888873418 - 0.01831563888873418 = 0.0
1.2340980408667956E-4 - 1.2340980408667956E-4 = 0.0
1.1253517471925912E-7 - 1.1253517471925912E-7 = 0.0
1.3887943864964021E-11 - 1.3887943997473953E-11 = -1.3250993165605518E-19
2.3195228302435696E-16 - 0.0012040908282411062 = -0.0012040908282408742
5.242885663363464E-22 - 3.6698962251221756E10 = -3.6698962251221756E10
I would say that Math.exp loses precision but I'm not really sure ;)
I am trying to calculate second order bessel functions (Y_v(x)) using Java. Where v, the order of the bessel function, is non integer.
Apache, I know, has a function to calculated first order bessel functions (J_v(x))
import org.apache.commons.math3.special.BesselJ;
BesselJ bj = new BesselJ(10.5);
double bjr = bj.value(r);
Which can calculate non-integer first order bessel functions (but not negative order functions). I do not believe it has an equivalent for second order.
I have found a formula for calculating second order bessel functions (equation 6.4.2 of Numerical Recipies among other places) which calculates second order bessel functions from first order functions.
However this equation requires the first order bessel functions to accept negative v values which the apache BesselJ function does not.
I have written a program to calculate BesselJ functions whch accept negative values using the formula (Numerical Recipes 6.4.1)
import org.apache.commons.math3.special.Gamma;
import org.apache.commons.math3.util.ArithmeticUtils;
private static int lmax;
private static double[][] Gammas;
private static int besselcount;
public static Double Bessel_J(double m, double x){
double BJ = 0.0;
for (int k = 0; k < besselcount;k++){
double kk = (double) k;
double llmm = (double) lmax;
double A = Math.pow(x/2.,(2.*kk)+m);
double B = Gammas[(int) (m+llmm+0.5)][k];
if (B==0.0||B==-0.0){break;}
BJ = BJ + A*B;
}
return BJ;
}
public static void main(String[] args) throws Exception {
besselcount = 80;
lmax = 20;
Gammas = new double[2*lmax+2][besselcount+1];
for (int n = 0;n <= ((2*lmax)+1);n++){
for (int m = 0;m <=besselcount;m++) {
double nn = (double) n;
double mm = (double) m;
double llmm = (double) lmax;
Gammas[n][m] = Math.pow(-1,m)/(ArithmeticUtils.factorialDouble(m)*Gamma.gamma(1.+nn-llmm-0.5+mm));
}
}
for (double x = 0.02; x < 50.0 ; x = x + 0.02){
double bj = Bessel_J(-10.5, x);
System.out.println(x+" "+bj);
}
}
(Having the gammas precalculated and stored in an array is just because of how the bessel function is used in the rest of the code, to avoid recalculating this unnecessarily)
The function I have written works for low x values but then looses stability. For the v = -10.5 value I have used after around x = 30. As shown in the figure.
On the wolfram alpha website is says mathematica uses the same equations to calculate bessel functions and mathematica's BesselJ function can calculate
Show[Plot[BesselJ[-10.5, x], {x, 0, 50}], ImageSize -> Full]
Without loosing stability.
Any advice on either how to correct my functions or alternative ways to calculate second order bessel functions using Java would be very much appreciated.
Please say if any clarification would be useful.
Thank you
I am using j2me and I need to get quite precise exp() for values up to 4.
Problem with the j2me is that it's Math library doesn't have pow() and exp() method. To solve this, I just used this method to implement pow():
public static double pow(double num1, double num2) {
double result = 1;
for (int i = 0; i < num2; i++)
result *= num1;
return result;
}
This enabled me to have exp functionality by using setting e as constant (2.718281828459045) and calling pow:
double calculation = (20.386 - (5132.000 / (t + 273.15)));
System.out.println("calc: " + pow(2.71,calculation));
calculation = pow(2.7182818284590452,calculation) * 1.33;
My problem is that result is quite inaccurate, for example if I compare math.exp and my pow method for number 3,75, results are like this:
Pow function returns: 54.5980031309658
Math function returns: 42.52108200006278
So I would need advice, how to implement exp functionality in j2me environment with highest precision possible.
I helped my self with bharath answer in this question: How to get the power of a number in J2ME
Since exp method is just pow, where we use Euler's number for the first argument, I used bharath method:
public double powSqrt(double x, double y)
{
int den = 1024, num = (int)(y*den), iterations = 10;
double n = Double.MAX_VALUE;
while( n >= Double.MAX_VALUE && iterations > 1)
{
n = x;
for( int i=1; i < num; i++ )n*=x;
if( n >= Double.MAX_VALUE )
{
iterations--;
den = (int)(den / 2);
num = (int)(y*den);
}
}
for( int i = 0; i <iterations; i++ )n = Math.sqrt(n);
return n;
}
Method call:
calculation = powSqrt(2.7182818284590452,calculation) * 1.33;
Result is almost as good as Math.pow() method.
PS:
I don't know if this is duplicated thread, if so you can delete it.
I'm trying to calculate the Mean Difference average of a set of data. I have two (supposedly equivalent) formulas which calculate this, with one being more efficient (O^n) than the other (O^n2).
The problem is that while the inefficient formula gives correct output, the efficient one does not. Just by looking at both formulas I had a hunch that they weren't equivalent, but wrote it off because the derivation was made by a statician in a scientific journal. So i'm assuming the problem is my translation. Can anyone help me translate the efficient function properly?
Inefficient formula:
Inefficient formula translation (Java):
public static double calculateMeanDifference(ArrayList<Integer> valuesArrayList)
{
int valuesArrayListSize = valuesArrayList.size();
int sum = 0;
for(int i = 0; i < valuesArrayListSize; i++)
{
for(int j = 0; j < valuesArrayListSize; j++)
sum += (i != j ? Math.abs(valuesArrayList.get(i) - valuesArrayList.get(j)) : 0);
}
return new Double( (sum * 1.0)/ (valuesArrayListSize * (valuesArrayListSize - 1)));
}
Efficient derived formula:
where (sorry, don't know how to use MathML on here):
x(subscript i) = the ith order statistic of the data set
x(bar) = the mean of the data set
Efficient derived formula translation (Java):
public static double calculateMean(ArrayList<Integer> valuesArrayList)
{
double sum = 0;
int valuesArrayListSize = valuesArrayList.size();
for(int i = 0; i < valuesArrayListSize; i++)
sum += valuesArrayList.get(i);
return sum / (valuesArrayListSize * 1.0);
}
public static double calculateMeanDifference(ArrayList<Integer> valuesArrayList)
{
double sum = 0;
double mean = calculateMean(valuesArrayList);
int size = valuesArrayList.size();
double rightHandTerm = mean * size * (size + 1);
double denominator = (size * (size - 1)) / 2.0;
Collections.sort(valuesArrayList);
for(int i = 0; i < size; i++)
sum += (i * valuesArrayList.get(i) - rightHandTerm);
double meanDifference = (2 * sum) / denominator;
return meanDifference;
}
My data set consists of a collection of integers each having a value bounded by the set [0,5].
Randomly generating such sets and using the two functions on them gives different results. The inefficient one seems to be the one producing results in line with what is being measured: the absolute average difference between any two values in the set.
Can anyone tell me what's wrong with my translation?
EDIT: I created a simpler implementation that is O(N) provided the all your data has values limited to a relatively small set.The formula sticks to the methodology of the first method and thus, gives identical results to it (unlike the derived formula). If it fits your use case, I suggest people use this instead of the derived efficient formula, especially since the latter seems to give negative values when N is small).
Efficient, non-derived translation (Java):
public static double calculateMeanDifference3(ArrayList<Integer> valuesArrayList)
{
HashMap<Integer, Double> valueCountsHashMap = new HashMap<Integer, Double>();
double size = valuesArrayList.size();
for(int i = 0; i < size; i++)
{
int currentValue = valuesArrayList.get(i);
if(!valueCountsHashMap.containsKey(currentValue))
valueCountsHashMap.put(currentValue, new Double(1));
else
valueCountsHashMap.put(currentValue, valueCountsHashMap.get(currentValue)+ 1);
}
double sum = 0;
for(Map.Entry<Integer, Double> valueCountKeyValuePair : valueCountsHashMap.entrySet())
{
int currentValue = valueCountKeyValuePair.getKey();
Double currentCount = valueCountKeyValuePair.getValue();
for(Map.Entry<Integer, Double> valueCountKeyValuePair1 : valueCountsHashMap.entrySet())
{
int loopValue = valueCountKeyValuePair1.getKey();
Double loopCount = valueCountKeyValuePair1.getValue();
sum += (currentValue != loopValue ? Math.abs(currentValue - loopValue) * loopCount * currentCount : 0);
}
}
return new Double( sum/ (size * (size - 1)));
}
Your interpretation of sum += (i * valuesArrayList.get(i) - rightHandTerm); is wrong, it should be sum += i * valuesArrayList.get(i);, then after your for, double meanDifference = ((2 * sum) - rightHandTerm) / denominator;
Both equations yields about the same value, but they are not equal. Still, this should help you a little.
You subtract rightHandTerm on each iteration, so it gets [over]multiplied to N.
The big Sigma in the nominator touches only (i x_i), not the right hand term.
One more note: mean * size == sum. You don't have to divide sum by N and then remultiply it back.