I tried to make a program (in Java) that calculates pi with the Chudnovsky algorithm but it has the output NaN (Not a Number). Please help me find mistakes in my code, or improve my code. (I don't have a lot of Java programming knowledge)
You can find Chudnovsky's algorithm here:
https://en.wikipedia.org/wiki/Chudnovsky_algorithm
here is my code:
package main;
public class Class1 {
public static void main(String[] args)
{
double nr1=0,nr2=0,nr3=0,pi=0;
int fo1=1, fo2=1, fo3=1;
for(int i=0; i<=20; i++){
for(int fl1=1; fl1<=(6*i); fl1++){fo1 = fo1 * fl1;}
for(int fl2=1; fl2<=(3*i); fl2++){fo2 = fo2 * fl2;}
for(int fl3=1; fl3<=(i); fl3++){fo3 = fo3 * fl3;}
nr1 = ( (Math.pow(-1, i)) * (fo1) * ((545140134*i) + 13591409) );
nr2 = ( (fo2) * (Math.pow(fo3, i)) * ( Math.pow(Math.pow(640320, 3), (i+(1/2)) )) );
nr3 = 12 * (nr1/nr2);
}
pi = 1/nr3;
System.out.println((Math.PI));
System.out.println(pi);
}
}
There are many issues here.
As Andy mentioned, 1/2 is not 0.5.
You are using integers to compute things like 120! which is completely out of bounds for any primitive type.
f01,f02,f03 should be initialized inside each loop, otherwise they grow even bigger
It is not trivial to fix it. You can take a look at
Error calculating pi using the Chudnovsky algorithm - Java
and
http://www.craig-wood.com/nick/articles/pi-chudnovsky/
for some hints, but don't expect built-in primitive types to work with that algorithm.
Related
I have a program that takes in anywhere from 20,000 to 500,000 velocity vectors and must output these vectors multiplied by some scalar. The program allows the user to set a variable accuracy, which is basically just how many decimal places to truncate to in the calculations. The program is quite slow at the moment, and I discovered that it's not because of multiplying a lot of numbers, it's because of the method I'm using to truncate floating point values.
I've already looked at several solutions on here for truncating decimals, like this one, and they mostly recommend DecimalFormat. This works great for formatting decimals once or twice to print nice user output, but is far too slow for hundreds of thousands of truncations that need to happen in a few seconds.
What is the most efficient way to truncate a floating-point value to n number of places, keeping execution time at utmost priority? I do not care whatsoever about resource usage, convention, or use of external libraries. Just whatever gets the job done the fastest.
EDIT: Sorry, I guess I should have been more clear. Here's a very simplified version of what I'm trying to illustrate:
import java.util.*;
import java.lang.*;
import java.text.DecimalFormat;
import java.math.RoundingMode;
public class MyClass {
static class Vector{
float x, y, z;
#Override
public String toString(){
return "[" + x + ", " + y + ", " + z + "]";
}
}
public static ArrayList<Vector> generateRandomVecs(){
ArrayList<Vector> vecs = new ArrayList<>();
Random rand = new Random();
for(int i = 0; i < 500000; i++){
Vector v = new Vector();
v.x = rand.nextFloat() * 10;
v.y = rand.nextFloat() * 10;
v.z = rand.nextFloat() * 10;
vecs.add(v);
}
return vecs;
}
public static void main(String args[]) {
int precision = 2;
float scalarToMultiplyBy = 4.0f;
ArrayList<Vector> velocities = generateRandomVecs();
System.out.println("First 10 raw vectors:");
for(int i = 0; i < 10; i++){
System.out.print(velocities.get(i) + " ");
}
/*
This is the code that I am concerned about
*/
DecimalFormat df = new DecimalFormat("##.##");
df.setRoundingMode(RoundingMode.DOWN);
long start = System.currentTimeMillis();
for(Vector v : velocities){
/* Highly inefficient way of truncating*/
v.x = Float.parseFloat(df.format(v.x * scalarToMultiplyBy));
v.y = Float.parseFloat(df.format(v.y * scalarToMultiplyBy));
v.z = Float.parseFloat(df.format(v.z * scalarToMultiplyBy));
}
long finish = System.currentTimeMillis();
long timeElapsed = finish - start;
System.out.println();
System.out.println("Runtime: " + timeElapsed + " ms");
System.out.println("First 10 multiplied and truncated vectors:");
for(int i = 0; i < 10; i++){
System.out.print(velocities.get(i) + " ");
}
}
}
The reason it is very important to do this is because a different part of the program will store trigonometric values in a lookup table. The lookup table will be generated to n places beforehand, so any velocity vector that has a float value to 7 places (i.e. 5.2387471) must be truncated to n places before lookup. Truncation is needed instead of rounding because in the context of this program, it is OK if a vector is slightly less than its true value, but not greater.
Lookup table for 2 decimal places:
...
8.03 -> -0.17511085919
8.04 -> -0.18494742685
8.05 -> -0.19476549993
8.06 -> -0.20456409661
8.07 -> -0.21434223706
...
Say I wanted to look up the cosines of each element in the vector {8.040844, 8.05813164, 8.065688} in the table above. Obviously, I can't look up these values directly, but I can look up {8.04, 8.05, 8.06} in the table.
What I need is a very fast method to go from {8.040844, 8.05813164, 8.065688} to {8.04, 8.05, 8.06}
The fastest way, which will introduce rounding error, is going to be to multiply by 10^n, call Math.rint, and to divide by 10^n.
That's...not really all that helpful, though, considering the introduced error, and -- more importantly -- that it doesn't actually buy anything. Why drop decimal points if it doesn't improve efficiency or anything? If it's about making the values shorter for display or the like, truncate then, but until then, your program will run as fast as possible if you just use full float precision.
I'm trying to take user input in the form of myMonthlyPayment, myAnnualInterestRate, and myPrincipal in order to calculate the number of months needed to pay off debt by using The formula I've attached to this post. What I have in eclipse for the formula right now is:
monthsNeeded = ((Math.log(myMonthlyPayment) - Math.log(myMonthlyPayment)
- ((myAnnualInterestRate / 1200.0) * myPrincipal))
/ ((Math.log(myAnnualInterestRate) / 1200.0) + 1.0));
I should be getting an output of 79 months with the inputs I'm using but instead I'm getting -62. I know the formula is correct, I'm almost positive I've made a mistake somewhere in the translation of it into Java. If someone could point it out that would be greatly appreciated!
So I've fixed it, with a sample input and output.
I didn't put much effort into making this code beautiful but you can see that even separating it into 3 parts using method extraction (although I didn't know how to name them, lacking the domain knowledge) made the code easier to understand.
public class Example {
public static void main(String[] args) {
double myMonthlyPayment = 2000;
double myAnnualInterestRate = 5;
double myPrincipal = 200000;
System.out.println(a(myMonthlyPayment));
System.out.println(b(myPrincipal, myAnnualInterestRate, myMonthlyPayment));
System.out.println(c(myAnnualInterestRate));
double monthsNeeded = (a(myMonthlyPayment) - b(myPrincipal, myAnnualInterestRate, myMonthlyPayment))
/ c(myAnnualInterestRate);
System.out.println(monthsNeeded);
}
private static double c(double myAnnualInterestRate) {
return Math.log((myAnnualInterestRate / 1200.0) + 1);
}
private static double b(double myPrinicipal, double myAnnualInterestRate, double myMonthlyPayment) {
return Math.log(myMonthlyPayment - (myAnnualInterestRate / 1200.0) * myPrinicipal);
}
private static double a(double myMonthlyPayment) {
return Math.log(myMonthlyPayment);
}
}
I think this is what you're looking for:
monthsNeeded = (Math.log(myMonthlyPayment) - Math.log(myMonthlyPayment - myAnnualInterestRate / 1200d * myPrincipal)) / Math.log(myAnnualInterestRate / 1200d + 1);
It seems that, in your solution, you weren't calculating your myAnnualInterestRate/1200*myPrincipal inside your second Math.log(...). You had also left some calculations outside of Math.log(...) in the bottom half of your equation.
If you have an equation that does an operation inside a natural log, when you convert that equation to Java code, the operation needs to still be done, inside the natural log:
ln(someNumber + 10)
would be converted to:
Math.log(someNumber + 10),
NOT:
Math.log(someNumber) + 10
Hope this helps and good luck. :)
I'm programming card and deck classes for a school assignment, and my shuffling method isn't consistently passing the test code for it. We are supposed to be using online resources specifically instead of grader/instructor support for this one, and I quickly found the Fisher Yates shuffle method, but I'm having trouble understanding some of the details of it. I'd like to incorporate some of what I came up with and some of it seems pretty similar. Can anyone explain what I'm missing and what it does? Here's my method:
public void shuffle() {
/**
* I'm trying an orginial idea for the shuffle method of taking the
* element at each index and switching it out with another element
* at a random index
*/
Card placeHolder;
int i;
for (int c = 0; c < cardNum; c++) {
i = (int) (Math.random() * (cardNum-1));
placeHolder = deckList[i];
deckList[i] = deckList[c];
deckList[c] = placeHolder;
}
}
You're really close. I'd recommend changing this:
i = (int) (Math.random() * (cardNum-1));
To this:
i = (int) (Math.random() * (cardNum - i) + i);
Or use ThreadLocalRandom.current().nextInt(origin, bound) (assuming you are on 1.7 or greater).
I have implemented Logistic Regression with Gradient Descent in Java. It doesn't seem to work well (It does not classify records properly; the probability of y=1 is a lot.) I don't know whether my implementation is correct.I have gone through the code several times and i am unable to find any bug. I have been following Andrew Ng's tutorials on Machine learning on Course Era. My Java implementation has 3 classes. namely :
DataSet.java : To read the data set
Instance.java : Has two members : 1. double[ ] x and 2. double label
Logistic.java : This is the main class that implements Logistic Regression with Gradient Descent.
This is my cost function:
J(Θ) = (- 1/m ) [Σmi=1 y(i) log( hΘ( x(i) ) ) + (1 - y(i) ) log(1 - hΘ (x(i)) )]
For the above Cost function, this is my Gradient Descent algorithm:
Repeat ( Θj := Θj - α Σmi=1 ( hΘ( x(i)) - y(i) ) x(i)j
(Simultaneously update all Θj )
)
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Logistic {
/** the learning rate */
private double alpha;
/** the weight to learn */
private double[] theta;
/** the number of iterations */
private int ITERATIONS = 3000;
public Logistic(int n) {
this.alpha = 0.0001;
theta = new double[n];
}
private double sigmoid(double z) {
return (1 / (1 + Math.exp(-z)));
}
public void train(List<Instance> instances) {
double[] temp = new double[3];
//Gradient Descent algorithm for minimizing theta
for(int i=1;i<=ITERATIONS;i++)
{
for(int j=0;j<3;j++)
{
temp[j]=theta[j] - (alpha * sum(j,instances));
}
//simulataneous updates of theta
for(int j=0;j<3;j++)
{
theta[j] = temp[j];
}
System.out.println(Arrays.toString(theta));
}
}
private double sum(int j,List<Instance> instances)
{
double[] x;
double prediction,sum=0,y;
for(int i=0;i<instances.size();i++)
{
x = instances.get(i).getX();
y = instances.get(i).getLabel();
prediction = classify(x);
sum+=((prediction - y) * x[j]);
}
return (sum/instances.size());
}
private double classify(double[] x) {
double logit = .0;
for (int i=0; i<theta.length;i++) {
logit += (theta[i] * x[i]);
}
return sigmoid(logit);
}
public static void main(String... args) throws FileNotFoundException {
//DataSet is a class with a static method readDataSet which reads the dataset
// Instance is a class with two members: double[] x, double label y
// x contains the features and y is the label.
List<Instance> instances = DataSet.readDataSet("data.txt");
// 3 : number of theta parameters corresponding to the features x
// x0 is always 1
Logistic logistic = new Logistic(3);
logistic.train(instances);
//Test data
double[]x = new double[3];
x[0]=1;
x[1]=45;
x[2] = 85;
System.out.println("Prob: "+logistic.classify(x));
}
}
Can anyone tell me what am I doing wrong?
Thanks in advance! :)
As I am studying logistic regression, I took the time to review your code in detail.
TLDR
In fact, it appears the algorithm is correct.
The reason you had so much false negatives or false positives is, I think, because of the hyper parameters you choose.
The model was under-trained so the hypothesis was under-fitting.
Details
I had to create the DataSet and Instance classes because you did not publish them, and set up a train data set and a test data set based on the Cryotherapy dataset.
See http://archive.ics.uci.edu/ml/datasets/Cryotherapy+Dataset+.
Then, using your same exact code (for the logistic regression part) and by choosing an alpha rate of 0.001 and a number of iterations of 100000, I got a precision rate of 80.64516129032258 percent on the test data set, which is not so bad.
I tried to get a better precision rate by tweaking manualy those hyper parameters but could not obtain any better result.
At this point, an enhancement would be to implement regularization, I suppose.
Gradient descent formula
In Andrew Ng's video about the the cost function and gradient descent, it is correct that the 1/m term is omitted.
A possible explanation is that the 1/m term is included in the alpha term.
Or maybe it's just an oversight.
See https://www.youtube.com/watch?v=TTdcc21Ko9A&index=36&list=PLLssT5z_DsK-h9vYZkQkYNWcItqhlRJLN&t=6m53s at 6m53s.
But if you watch Andrew Ng's video about regularization and logistic regression you'll notice that the term 1/m is clearly present in the formula.
See https://www.youtube.com/watch?v=IXPgm1e0IOo&index=42&list=PLLssT5z_DsK-h9vYZkQkYNWcItqhlRJLN&t=2m19s at 2m19s.
I've written an Adaline Neural Network. Everything that I have compiles, so I know that there isn't a problem with what I've written, but how do I know that I have to algorithm correct? When I try training the network, my computer just says the application is running and it just goes. After about 2 minutes I just stopped it.
Does training normally take this long (I have 10 parameters and 669 observations)?
Do I just need to let it run longer?
Hear is my train method
public void trainNetwork()
{
int good = 0;
//train until all patterns are good.
while(good < trainingData.size())
{
for(int i=0; i< trainingData.size(); i++)
{
this.setInputNodeValues(trainingData.get(i));
adalineNode.run();
if(nodeList.get(nodeList.size()-1).getValue(Constants.NODE_VALUE) != adalineNode.getValue(Constants.NODE_VALUE))
{
adalineNode.learn();
}
else
{
good++;
}
}
}
}
And here is my learn method
public void learn()
{
Double nodeValue = value.get(Constants.NODE_VALUE);
double nodeError = nodeValue * -2.0;
error.put(Constants.NODE_ERROR, nodeError);
BaseLink link;
int count = inLinks.size();
double delta;
for(int i = 0; i < count; i++)
{
link = inLinks.get(i);
Double learningRate = value.get(Constants.LEARNING_RATE);
Double value = inLinks.get(i).getInValue(Constants.NODE_VALUE);
delta = learningRate * value * nodeError;
inLinks.get(i).updateWeight(delta);
}
}
And here is my run method
public void run()
{
double total = 0;
//find out how many input links there are
int count = inLinks.size();
for(int i = 0; i< count-1; i++)
{
//grab a specific link in sequence
BaseLink specificInLink = inLinks.get(i);
Double weightedValue = specificInLink.weightedInValue(Constants.NODE_VALUE);
total += weightedValue;
}
this.setValue(Constants.NODE_VALUE, this.transferFunction(total));
}
These functions are part of a library that I'm writing. I have the entire thing on Github here. Now that everything is written, I just don't know how I should go about actually testing to make sure that I have the training method written correctly.
I asked a similar question a few months ago.
Ten parameters with 669 observations is not a large data set. So there is probably an issue with your algorithm. There are two things you can do that will make debugging your algorithm much easier:
Print the sum of squared errors at the end of each iteration. This will help you determine if the algorithm is converging (at all), stuck at a local minimum, or just very slowly converging.
Test your code on a simple data set. Pick something easy like a two-dimensional input that you know is linearly separable. Will your algorithm learn a simple AND function of two inputs? If so, will it lean an XOR function (2 inputs, 2 hidden nodes, 2 outputs)?
You should be adding debug/test mode messages to watch if the weights are getting saturated and more converged. It is likely that good < trainingData.size() is not happening.
Based on Double nodeValue = value.get(Constants.NODE_VALUE); I assume NODE_VALUE is of type Double ? If that's the case then this line nodeList.get(nodeList.size()-1).getValue(Constants.NODE_VALUE) != adalineNode.getValue(Constants.NODE_VALUE) may not really converge exactly as it is of type double with lot of other parameters involved in obtaining its value and your convergence relies on it. Typically while training a neural network you stop when the convergence is within an acceptable error limit (not a strict equality like you are trying to check).
Hope this helps