Flipping horizontal asterisk histogram to a vertical one in java - java

I am trying to create a vertical histogram from a horizontal histogram. I have tried with a similar nested loop setup but I can't seem to do it without breaking the code. I'm slowly learning from a textbook so I've only had experience with a limited number of functions.
The scaling with spaces in a vertical graph is a lot more difficult than I could manage unfortunately.
public static void main(String atgs[]) {
int[] distribution = {0,1,8,59,215,703,1848,3975,8077,13937,22195,31628,
41711,51099,57142,59959,59670,55756,48850,40931,32583,
24995,18217,12794,8623,5577,3601,2272,1259,764,464,246,
153,80,39,22,12,6,3,0};
final int MAX_COUNTS = distribution.length;
System.out.println(String.format("%3s %-11s %-11s %-11s %-11s %-11s %-11s %-11s", " ", "0", "10000", "20000", "30000", "40000", "50000", "60000"));
System.out.println(" -----------------------------------------------------------------------------");
System.out.println(String.format("%3s %-11s %-11s %-11s %-11s %-11s %-11s %-11s", " ", "|", "|", "|", "|", "|", "|", "|"));
for (int i = 0; i < MAX_COUNTS; i++) {
if (i % 10 == 0) {
System.out.print(String.format("%3s %-1s", String.valueOf(i), "|"));
int n = distribution[i] / 1000 + 1;
for (int j = 1; j <= n; j++) {
System.out.print(String.format("%1s", "*"));
}
System.out.println();
} else {
System.out.print(String.format("%-3s %-1s", " ", "|"));
int n = distribution[i] / 1000 + 1;
for (int j = 1; j <= n; j++) {
System.out.print(String.format("%1s", "*"));
}
System.out.println();
}
}
}

Creating a vertical histogram is more complicated than a horizontal histogram.
Here are the results of your distribution array.
60,000- |
| * *
| * * *
| * * * *
| * * * *
50,000- | * * * * *
| * * * * * *
| * * * * * *
| * * * * * *
| * * * * * *
40,000- | * * * * * * * *
| * * * * * * * *
| * * * * * * * *
| * * * * * * * *
| * * * * * * * * *
30,000- | * * * * * * * * * *
| * * * * * * * * * *
| * * * * * * * * * *
| * * * * * * * * * * *
| * * * * * * * * * * * *
20,000- | * * * * * * * * * * * *
| * * * * * * * * * * * * *
| * * * * * * * * * * * * *
| * * * * * * * * * * * * *
| * * * * * * * * * * * * * * *
10,000- | * * * * * * * * * * * * * * *
| * * * * * * * * * * * * * * * * *
| * * * * * * * * * * * * * * * * *
| * * * * * * * * * * * * * * * * * *
| * * * * * * * * * * * * * * * * * * * * *
0- | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - -
0 10 20 30
The biggest "trick" I did was to create the vertical histogram upside down. In other words, I created the X-axis label line first, then the dashed line, then the histogram lines from the bottom up. I saved all the lines in a java.util.List, then printed the output lines in reverse order.
I broke the code up into seven methods, not including the main method. I did this so I could focus on one part of the vertical histogram at a time.
I did not write all this code in one shot. I built one vertical histogram line at a time. I built the vertical histogram first, then added the Y-Axis labels. I tested. I probably ran 50 - 70 tests before I completed the code.
I used a StringBuilder to construct each line. You could concatenate String segments together, but a StringBuilder is more efficient.
Here's the complete, runnable code. I hope you review the code and try to understand what I did.
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
public class VerticalHistogram {
public static void main(String atgs[]) {
VerticalHistogram vh = new VerticalHistogram();
int[] distribution = { 0, 1, 8, 59, 215, 703, 1848, 3975, 8077,
13937, 22195, 31628, 41711, 51099, 57142, 59959,
59670, 55756, 48850, 40931, 32583, 24995, 18217,
12794, 8623, 5577, 3601, 2272, 1259, 764, 464, 246,
153, 80, 39, 22, 12, 6, 3, 0 };
vh.createVerticalHistogram(distribution);
}
private NumberFormat numberFormat;
public VerticalHistogram() {
this.numberFormat = NumberFormat.getIntegerInstance();
}
public void createVerticalHistogram(int[] distribution) {
int maximum = calculateMaximum(distribution);
maximum = roundUp(maximum, 1000);
// 30 is maximum height of histogram
int interval = maximum / 30;
int labelInterval = interval * 5;
// System.out.println(maximum + " " + interval);
List<String> output = generateVerticalHistogram(distribution,
interval, labelInterval, maximum);
for(int i = output.size() - 1; i >= 0; i--) {
System.out.println(output.get(i));
}
}
private int calculateMaximum(int[] distribution) {
int max = distribution[0];
for (int i = 1; i < distribution.length; i++) {
max = Math.max(max, distribution[i]);
}
return max;
}
private List<String> generateVerticalHistogram(int[] distribution,
int interval, int labelInterval, int max) {
List<String> output = new ArrayList<>();
output.add(generateXLabels(distribution));
output.add(generateXAxis(distribution));
for (int value = interval; value <= max; value += interval) {
output.add(generateYValue(distribution, value, labelInterval));
}
return output;
}
private String generateXLabels(int[] distribution) {
StringBuilder builder = new StringBuilder();
builder.append(" ");
for (int i = 0; i < distribution.length; i++) {
if (i % 10 == 0) {
builder.append(i);
} else {
builder.append(" ");
}
}
return builder.toString();
}
private String generateXAxis(int[] distribution) {
StringBuilder builder = new StringBuilder();
builder.append(" ");
builder.append(numberFormat.format(0));
builder.append("- ");
for (int i = 0; i < distribution.length; i++) {
if (i % 5 == 0) {
builder.append("| ");
} else {
builder.append("- ");
}
}
return builder.toString();
}
private String generateYValue(int[] distribution, int value,
int labelInterval) {
StringBuilder builder = new StringBuilder();
if (value % labelInterval == 0) {
String label = numberFormat.format(value);
int margin = 8 - label.length();
for (int i = 0; i < margin; i++) {
builder.append(" ");
}
builder.append(label).append("- | ");
} else {
builder.append(" | ");
}
for (int i = 0; i < distribution.length; i++) {
if (distribution[i] >= value) {
builder.append("* ");
} else {
builder.append(" ");
}
}
return builder.toString();
}
private int roundUp(int max, int factor) {
return (max + factor - 1) / factor * factor;
}
}

Related

how i can solve this in recursion method

actually I worked with diamond shape recursively but showing me problem and i don't know how i solve it here the shape :
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
just up ..
this is my code :
public static void draw(int shape, int space, PrintWriter output) {
boolean x = true;
if (shape < 1) {
System.out.print("");
} else if (x) {
draw(shape - 2, space - 1, output);
row(shape, space, output);
} else {
row(shape, space, output);
draw(shape - 2, space - 1, output);
}
if (space == shape) {
draw(shape - 2, space - 1, output);
}
}
public static void row(int shape, int space, PrintWriter output) {
for (int i = 0; i < space; i++) {
if (i < space - shape) {
System.out.print(" ");// print space
} else {
System.out.print("* ");//print a star
}
}
System.out.println("");
}
the program java i/o and size diamond : 3 ,5 ,7 and 33
There are several types of recursion: 1) preorder, 2) inorder, and 3) postorder. Here you actually need to do a combination of preorder and postorder recursion. In words:
Draw a line of stars
Draw the rest of the diamond (this is the recursive part)
Draw another line of stars the same length as the one in step 1
Hopefully this will help you see how you can fix your code to get the diamond shape you want. Notice how I am thinking about the solution to the problem in English without worrying about any Java syntax. The only technical detail that I use is the idea of recursion, but I still describe it in words.

how to convert os grid reference to longitude and latitude in java?

I'm looking to convert OS Grid Reference to longitude and latitude, I'm using the jcoord library in Android studio, http://www.jstott.me.uk/jcoord/
I'm interested how I would connect this to a button that on on activity you can type in a grid reference on a edit text, and click convert (Which will do the magic formula) and will show the longitude and latitude below?
Basically I want to make a user interface, with being able to test this on my phone
I believe the formula will be done in the OSRef.java, with the code being the following:
public class OSRef extends Activity implements View.OnClickListener {
EditText osGridNumber;
View convertButton;
TextView latLongBox;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
convertButton = findViewById(R.id.cmdConvert);
convertButton.setOnClickListener(this);
osGridNumber = (EditText) findViewById(R.id.edtOS);
latLongBox = (TextView) findViewById(R.id.txtLngLat);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.cmdConvert:
break;
}
}
/**
* Easting
*/
private double easting;
/**
* Northing
*/
private double northing;
/**
* Create a new Ordnance Survey grid reference.
*
* #param easting the easting in metres
* #param northing the northing in metres
* #since 1.0
*/
public OSRef(double easting, double northing) {
this.easting = easting;
this.northing = northing;
}
/**
* Take a string formatted as a six-figure OS grid reference (e.g. "TG514131")
* and create a new OSRef object that represents that grid reference. The
* first character must be H, N, S, O or T. The second character can be any
* uppercase character from A through Z excluding I.
*
* #param ref a String representing a six-figure Ordnance Survey grid reference
* in the form XY123456
* #throws IllegalArgumentException if ref is not of the form XY123456
* #since 1.0
*/
public OSRef(String ref) throws IllegalArgumentException {
// if (ref.matches(""))
char char1 = ref.charAt(0);
char char2 = ref.charAt(1);
// Thanks to Nick Holloway for pointing out the radix bug here
int east = Integer.parseInt(ref.substring(2, 5)) * 100;
int north = Integer.parseInt(ref.substring(5, 8)) * 100;
if (char1 == 'H') {
north += 1000000;
} else if (char1 == 'N') {
north += 500000;
} else if (char1 == 'O') {
north += 500000;
east += 500000;
} else if (char1 == 'T') {
east += 500000;
}
int char2ord = char2;
if (char2ord > 73)
char2ord--; // Adjust for no I
double nx = ((char2ord - 65) % 5) * 100000;
double ny = (4 - Math.floor((char2ord - 65) / 5)) * 100000;
easting = east + nx;
northing = north + ny;
}
/**
* Return a String representation of this OSGB grid reference showing the
* easting and northing.
*
* #return a String represenation of this OSGB grid reference
* #since 1.0
*/
public String toString() {
return "(" + easting + ", " + northing + ")";
}
/**
* Return a String representation of this OSGB grid reference using the
* six-figure notation in the form XY123456
*
* #return a String representing this OSGB grid reference in six-figure
* notation
* #since 1.0
*/
public String toSixFigureString() {
int hundredkmE = (int) Math.floor(easting / 100000);
int hundredkmN = (int) Math.floor(northing / 100000);
String firstLetter;
if (hundredkmN < 5) {
if (hundredkmE < 5) {
firstLetter = "S";
} else {
firstLetter = "T";
}
} else if (hundredkmN < 10) {
if (hundredkmE < 5) {
firstLetter = "N";
} else {
firstLetter = "O";
}
} else {
firstLetter = "H";
}
int index = 65 + ((4 - (hundredkmN % 5)) * 5) + (hundredkmE % 5);
// int ti = index;
if (index >= 73)
index++;
String secondLetter = Character.toString((char) index);
int e = (int) Math.floor((easting - (100000 * hundredkmE)) / 100);
int n = (int) Math.floor((northing - (100000 * hundredkmN)) / 100);
String es = "" + e;
if (e < 100)
es = "0" + es;
if (e < 10)
es = "0" + es;
String ns = "" + n;
if (n < 100)
ns = "0" + ns;
if (n < 10)
ns = "0" + ns;
return firstLetter + secondLetter + es + ns;
}
/**
* Convert this OSGB grid reference to a latitude/longitude pair using the
* OSGB36 datum. Note that, the LatLng object may need to be converted to the
* WGS84 datum depending on the application.
*
* #return a LatLng object representing this OSGB grid reference using the
* OSGB36 datum
* #since 1.0
*/
public LatLng toLatLng() {
double OSGB_F0 = 0.9996012717;
double N0 = -100000.0;
double E0 = 400000.0;
double phi0 = Math.toRadians(49.0);
double lambda0 = Math.toRadians(-2.0);
double a = RefEll.AIRY_1830.getMaj();
double b = RefEll.AIRY_1830.getMin();
double eSquared = RefEll.AIRY_1830.getEcc();
double phi = 0.0;
double lambda = 0.0;
double E = this.easting;
double N = this.northing;
double n = (a - b) / (a + b);
double M = 0.0;
double phiPrime = ((N - N0) / (a * OSGB_F0)) + phi0;
do {
M =
(b * OSGB_F0)
* (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n)) * (phiPrime - phi0))
- (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))
* Math.sin(phiPrime - phi0) * Math.cos(phiPrime + phi0))
+ ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))
* Math.sin(2.0 * (phiPrime - phi0)) * Math
.cos(2.0 * (phiPrime + phi0))) - (((35.0 / 24.0) * n * n * n)
* Math.sin(3.0 * (phiPrime - phi0)) * Math
.cos(3.0 * (phiPrime + phi0))));
phiPrime += (N - N0 - M) / (a * OSGB_F0);
} while ((N - N0 - M) >= 0.001);
double v =
a * OSGB_F0
* Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -0.5);
double rho =
a * OSGB_F0 * (1.0 - eSquared)
* Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -1.5);
double etaSquared = (v / rho) - 1.0;
double VII = Math.tan(phiPrime) / (2 * rho * v);
double VIII =
(Math.tan(phiPrime) / (24.0 * rho * Math.pow(v, 3.0)))
* (5.0 + (3.0 * Util.tanSquared(phiPrime)) + etaSquared - (9.0 * Util
.tanSquared(phiPrime) * etaSquared));
double IX =
(Math.tan(phiPrime) / (720.0 * rho * Math.pow(v, 5.0)))
* (61.0 + (90.0 * Util.tanSquared(phiPrime)) + (45.0 * Util
.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
double X = Util.sec(phiPrime) / v;
double XI =
(Util.sec(phiPrime) / (6.0 * v * v * v))
* ((v / rho) + (2 * Util.tanSquared(phiPrime)));
double XII =
(Util.sec(phiPrime) / (120.0 * Math.pow(v, 5.0)))
* (5.0 + (28.0 * Util.tanSquared(phiPrime)) + (24.0 * Util
.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
double XIIA =
(Util.sec(phiPrime) / (5040.0 * Math.pow(v, 7.0)))
* (61.0
+ (662.0 * Util.tanSquared(phiPrime))
+ (1320.0 * Util.tanSquared(phiPrime) * Util
.tanSquared(phiPrime)) + (720.0 * Util.tanSquared(phiPrime)
* Util.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
phi =
phiPrime - (VII * Math.pow(E - E0, 2.0))
+ (VIII * Math.pow(E - E0, 4.0)) - (IX * Math.pow(E - E0, 6.0));
lambda =
lambda0 + (X * (E - E0)) - (XI * Math.pow(E - E0, 3.0))
+ (XII * Math.pow(E - E0, 5.0)) - (XIIA * Math.pow(E - E0, 7.0));
return new LatLng(Math.toDegrees(phi), Math.toDegrees(lambda));
}
/**
* Get the easting.
*
* #return the easting in metres
* #since 1.0
*/
public double getEasting() {
return easting;
}
/**
* Get the northing.
*
* #return the northing in metres
* #since 1.0
*/
public double getNorthing() {
return northing;
}
}
Thanks in advance

Java- Optimizing a root finding algorithm

I wrote the following Java code to find zeroes for the Riemann-Siegel Z(t) function. I am wondering if I can optimize the code so that it doesn't take 36 hours to evaluate 0 < t < 1000000 (might not be possible though).
Through the findRoots() method inside the code sample below, can I adjust
double i = 0;
while (i < 1000000) {
i+= 0.001;
if(sign(func.value(i)) != sign(func.value(i+0.001))) {
set.add(f.solve(1000, func, i, i+0.001));
}
}
to do something faster? I am looking to increase i by 0.001 due to my investigation of the zeta function. Could I change this part so that the code doesn't take 36 hours to evaluate 0 < t < 1000000 while keeping i = 0.001?
The full program is pasted below. I am looking to change the part highlighted above.
Note: I am using a LinkedHashSet because I would like the output of the zeroes to be ordered when they are printed.
/**************************************************************************
**
** Apply Riemann-Siegel Formula for Lehmer's Phenomenon
**
**************************************************************************
** Axion004
** 09/30/2015
**************************************************************************/
import java.util.Iterator;
import java.util.LinkedHashSet;
//These two imports are from the Apache Commons Math library
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.solvers.BracketingNthOrderBrentSolver;
public class RiemannSiegel{
public static void main(String[] args){
SiegelMain();
}
// Main method
public static void SiegelMain() {
System.out.println("RS- Zeroes inside the critical line for " +
"Zeta(1/2 + it). The t values are referenced below.");
System.out.println();
findRoots();
}
/**
* The sign of a calculated double value.
* #param x - the double value.
* #return the sign in -1, 1, or 0 format.
*/
private static int sign(double x) {
if (x < 0.0)
return -1;
else if (x > 0.0)
return 1;
else
return 0;
}
/**
* Finds the roots of a specified function through the
* BracketingNthOrderBrentSolver from the Apache Commons Math library.
* See http://commons.apache.org/proper/commons-math/apidocs/org/
* apache/commons/math3/analysis/solvers/BracketingNthOrderBrentSolver
* .html
* The zeroes inside the interval of 0 < t < 10000 are printed from
* a LinkedHashSet.
*/
public static void findRoots() {
BracketingNthOrderBrentSolver f = new
BracketingNthOrderBrentSolver(1e-10, 10);
UnivariateFunction func = new UnivariateFunction() {
public double value(double x) {
return RiemennZ(x, 4);
}
};
LinkedHashSet<Double> set = new LinkedHashSet<>();
// Adjust values to see different zeroes
// Test adjusting values to understand the code
double i = 0;
while (i < 1000000) {
i+= 0.001;
if(sign(func.value(i)) != sign(func.value(i+0.001))) {
set.add(f.solve(1000, func, i, i+0.001));
}
}
for(Double s: set)
System.out.println(s);
}
/**
* Riemann-Siegel theta function using the approximation by the
* Stirling series.
* #param t - the value of t inside the Z(t) function.
* #return Stirling's approximation for theta(t).
*/
public static double theta (double t) {
return (t/2.0 * Math.log(t/(2.0*Math.PI)) - t/2.0 - Math.PI/8.0
+ 1.0/(48.0*Math.pow(t, 1)) + 7.0/(5760*Math.pow(t, 3)));
}
/**
* Computes Math.Floor of the absolute value term passed in as t.
* #param t - the value of t inside the Z(t) function.
* #return Math.floor of the absolute value of t.
*/
public static double fAbs(double t) {
return Math.floor(Math.abs(t));
}
/**
* Riemann-Siegel Z(t) function implemented per the Riemenn Siegel
* formula. See http://mathworld.wolfram.com/Riemann-SiegelFormula.html
* for details
* #param t - the value of t inside the Z(t) function.
* #param r - referenced for calculating the remainder terms by the
* Taylor series approximations.
* #return the approximate value of Z(t) through the Riemann-Siegel
* formula
*/
public static double RiemennZ(double t, int r) {
double twopi = Math.PI * 2.0;
double val = Math.sqrt(t/twopi);
double n = fAbs(val);
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += (Math.cos(theta(t) - t * Math.log(i))) / Math.sqrt(i);
}
sum = 2.0 * sum;
double remainder;
double frac = val - n;
int k = 0;
double R = 0.0;
// Necessary to individually calculate each remainder term by using
// Taylor Series co-efficients. These coefficients are defined below.
while (k <= r) {
R = R + C(k, 2.0*frac-1.0) * Math.pow(t / twopi,
((double) k) * -0.5);
k++;
}
remainder = Math.pow(-1, (int)n-1) * Math.pow(t / twopi, -0.25) * R;
return sum + remainder;
}
/**
* C terms for the Riemann-Siegel formula. See
* https://web.viu.ca/pughg/thesis.d/masters.thesis.pdf for details.
* Calculates the Taylor Series coefficients for C0, C1, C2, C3,
* and C4.
* #param n - the number of coefficient terms to use.
* #param z - referenced per the Taylor series calculations.
* #return the Taylor series approximation of the remainder terms.
*/
public static double C (int n, double z) {
if (n==0)
return(.38268343236508977173 * Math.pow(z, 0.0)
+.43724046807752044936 * Math.pow(z, 2.0)
+.13237657548034352332 * Math.pow(z, 4.0)
-.01360502604767418865 * Math.pow(z, 6.0)
-.01356762197010358089 * Math.pow(z, 8.0)
-.00162372532314446528 * Math.pow(z,10.0)
+.00029705353733379691 * Math.pow(z,12.0)
+.00007943300879521470 * Math.pow(z,14.0)
+.00000046556124614505 * Math.pow(z,16.0)
-.00000143272516309551 * Math.pow(z,18.0)
-.00000010354847112313 * Math.pow(z,20.0)
+.00000001235792708386 * Math.pow(z,22.0)
+.00000000178810838580 * Math.pow(z,24.0)
-.00000000003391414390 * Math.pow(z,26.0)
-.00000000001632663390 * Math.pow(z,28.0)
-.00000000000037851093 * Math.pow(z,30.0)
+.00000000000009327423 * Math.pow(z,32.0)
+.00000000000000522184 * Math.pow(z,34.0)
-.00000000000000033507 * Math.pow(z,36.0)
-.00000000000000003412 * Math.pow(z,38.0)
+.00000000000000000058 * Math.pow(z,40.0)
+.00000000000000000015 * Math.pow(z,42.0));
else if (n==1)
return(-.02682510262837534703 * Math.pow(z, 1.0)
+.01378477342635185305 * Math.pow(z, 3.0)
+.03849125048223508223 * Math.pow(z, 5.0)
+.00987106629906207647 * Math.pow(z, 7.0)
-.00331075976085840433 * Math.pow(z, 9.0)
-.00146478085779541508 * Math.pow(z,11.0)
-.00001320794062487696 * Math.pow(z,13.0)
+.00005922748701847141 * Math.pow(z,15.0)
+.00000598024258537345 * Math.pow(z,17.0)
-.00000096413224561698 * Math.pow(z,19.0)
-.00000018334733722714 * Math.pow(z,21.0)
+.00000000446708756272 * Math.pow(z,23.0)
+.00000000270963508218 * Math.pow(z,25.0)
+.00000000007785288654 * Math.pow(z,27.0)
-.00000000002343762601 * Math.pow(z,29.0)
-.00000000000158301728 * Math.pow(z,31.0)
+.00000000000012119942 * Math.pow(z,33.0)
+.00000000000001458378 * Math.pow(z,35.0)
-.00000000000000028786 * Math.pow(z,37.0)
-.00000000000000008663 * Math.pow(z,39.0)
-.00000000000000000084 * Math.pow(z,41.0)
+.00000000000000000036 * Math.pow(z,43.0)
+.00000000000000000001 * Math.pow(z,45.0));
else if (n==2)
return(+.00518854283029316849 * Math.pow(z, 0.0)
+.00030946583880634746 * Math.pow(z, 2.0)
-.01133594107822937338 * Math.pow(z, 4.0)
+.00223304574195814477 * Math.pow(z, 6.0)
+.00519663740886233021 * Math.pow(z, 8.0)
+.00034399144076208337 * Math.pow(z,10.0)
-.00059106484274705828 * Math.pow(z,12.0)
-.00010229972547935857 * Math.pow(z,14.0)
+.00002088839221699276 * Math.pow(z,16.0)
+.00000592766549309654 * Math.pow(z,18.0)
-.00000016423838362436 * Math.pow(z,20.0)
-.00000015161199700941 * Math.pow(z,22.0)
-.00000000590780369821 * Math.pow(z,24.0)
+.00000000209115148595 * Math.pow(z,26.0)
+.00000000017815649583 * Math.pow(z,28.0)
-.00000000001616407246 * Math.pow(z,30.0)
-.00000000000238069625 * Math.pow(z,32.0)
+.00000000000005398265 * Math.pow(z,34.0)
+.00000000000001975014 * Math.pow(z,36.0)
+.00000000000000023333 * Math.pow(z,38.0)
-.00000000000000011188 * Math.pow(z,40.0)
-.00000000000000000416 * Math.pow(z,42.0)
+.00000000000000000044 * Math.pow(z,44.0)
+.00000000000000000003 * Math.pow(z,46.0));
else if (n==3)
return(-.00133971609071945690 * Math.pow(z, 1.0)
+.00374421513637939370 * Math.pow(z, 3.0)
-.00133031789193214681 * Math.pow(z, 5.0)
-.00226546607654717871 * Math.pow(z, 7.0)
+.00095484999985067304 * Math.pow(z, 9.0)
+.00060100384589636039 * Math.pow(z,11.0)
-.00010128858286776622 * Math.pow(z,13.0)
-.00006865733449299826 * Math.pow(z,15.0)
+.00000059853667915386 * Math.pow(z,17.0)
+.00000333165985123995 * Math.pow(z,19.0)
+.00000021919289102435 * Math.pow(z,21.0)
-.00000007890884245681 * Math.pow(z,23.0)
-.00000000941468508130 * Math.pow(z,25.0)
+.00000000095701162109 * Math.pow(z,27.0)
+.00000000018763137453 * Math.pow(z,29.0)
-.00000000000443783768 * Math.pow(z,31.0)
-.00000000000224267385 * Math.pow(z,33.0)
-.00000000000003627687 * Math.pow(z,35.0)
+.00000000000001763981 * Math.pow(z,37.0)
+.00000000000000079608 * Math.pow(z,39.0)
-.00000000000000009420 * Math.pow(z,41.0)
-.00000000000000000713 * Math.pow(z,43.0)
+.00000000000000000033 * Math.pow(z,45.0)
+.00000000000000000004 * Math.pow(z,47.0));
else
return(+.00046483389361763382 * Math.pow(z, 0.0)
-.00100566073653404708 * Math.pow(z, 2.0)
+.00024044856573725793 * Math.pow(z, 4.0)
+.00102830861497023219 * Math.pow(z, 6.0)
-.00076578610717556442 * Math.pow(z, 8.0)
-.00020365286803084818 * Math.pow(z,10.0)
+.00023212290491068728 * Math.pow(z,12.0)
+.00003260214424386520 * Math.pow(z,14.0)
-.00002557906251794953 * Math.pow(z,16.0)
-.00000410746443891574 * Math.pow(z,18.0)
+.00000117811136403713 * Math.pow(z,20.0)
+.00000024456561422485 * Math.pow(z,22.0)
-.00000002391582476734 * Math.pow(z,24.0)
-.00000000750521420704 * Math.pow(z,26.0)
+.00000000013312279416 * Math.pow(z,28.0)
+.00000000013440626754 * Math.pow(z,30.0)
+.00000000000351377004 * Math.pow(z,32.0)
-.00000000000151915445 * Math.pow(z,34.0)
-.00000000000008915418 * Math.pow(z,36.0)
+.00000000000001119589 * Math.pow(z,38.0)
+.00000000000000105160 * Math.pow(z,40.0)
-.00000000000000005179 * Math.pow(z,42.0)
-.00000000000000000807 * Math.pow(z,44.0)
+.00000000000000000011 * Math.pow(z,46.0)
+.00000000000000000004 * Math.pow(z,48.0));
}
}

Haralick Java implementation, calculation of texture features

I have found Haralick's algorithm already implemented. It is used to get some feature with the help of Gray-Level Co-occurence matrices.
Now i have problems getting it to work. There are no exceptions. The code is fine. I'm not sure where to begin. Can someone help me with the first steps?How to i get a texture feature?
Below you can find the complete Haralick source code:
package de.lmu.dbs.jfeaturelib.features;
import Jama.Matrix;
import de.lmu.dbs.jfeaturelib.Progress;
import de.lmu.ifi.dbs.utilities.Arrays2;
import ij.plugin.filter.PlugInFilter;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;
import java.util.Arrays;
import java.util.EnumSet;
/**
* Haralick texture features
*
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
* <pre>
* #article{haralick1973textural,
* title={Textural features for image classification},
* author={Haralick, R.M. and Shanmugam, K. and Dinstein, I.},
* journal={Systems, Man and Cybernetics, IEEE Transactions on},
* volume={3},
* number={6},
* pages={610--621},
* year={1973},
* publisher={IEEE}
* }
* </pre>
*
* #author graf
*/
public class Haralick extends AbstractFeatureDescriptor {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES = 32;
/**
* p_(x+y) statistics
*/
private double[] p_x_plus_y = new double[2 * NUM_GRAY_VALUES - 1];
/**
* p_(x-y) statistics
*/
private double[] p_x_minus_y = new double[NUM_GRAY_VALUES];
/**
* row mean value
*/
private double mu_x = 0;
/**
* column mean value
*/
private double mu_y = 0;
/**
* row variance
*/
private double var_x = 0;
/**
* column variance
*/
private double var_y = 0;
/**
* HXY1 statistics
*/
private double hx = 0;
/**
* HXY2 statistics
*/
private double hy = 0;
/**
* HXY1 statistics
*/
private double hxy1 = 0;
/**
* HXY2 statistics
*/
private double hxy2 = 0;
/**
* p_x statistics
*/
private double[] p_x = new double[NUM_GRAY_VALUES];
/**
* p_y statistics
*/
private double[] p_y = new double[NUM_GRAY_VALUES];
// -
private int haralickDist;
double[] features = null;
/**
* Constructs a haralick detector with default parameters.
*/
public Haralick() {
this.haralickDist = 1;
}
/**
* Constructs a haralick detector.
*
* #param haralickDist Integer for haralick distribution
*/
public Haralick(int haralickDist) {
this.haralickDist = haralickDist;
}
/**
* Defines the capability of the algorithm.
*
* #see PlugInFilter
* #see #supports()
*/
#Override
public EnumSet<Supports> supports() {
EnumSet set = EnumSet.of(
Supports.NoChanges,
Supports.DOES_8C,
Supports.DOES_8G,
Supports.DOES_RGB);
return set;
}
/**
* Starts the haralick detection.
*
* #param ip ImageProcessor of the source image
*/
#Override
public void run(ImageProcessor ip) {
if (!ByteProcessor.class.isAssignableFrom(ip.getClass())) {
ip = ip.convertToByte(true);
}
firePropertyChange(Progress.START);
process((ByteProcessor) ip);
addData(features);
firePropertyChange(Progress.END);
}
/**
* Returns information about the getFeature
*/
#Override
public String getDescription() {
StringBuilder sb = new StringBuilder();
sb.append("Haralick features: ");
sb.append("Angular 2nd moment, ");
sb.append("Contrast, ");
sb.append("Correlation, ");
sb.append("variance, ");
sb.append("Inverse Difference Moment, ");
sb.append("Sum Average, ");
sb.append("Sum Variance, ");
sb.append("Sum Entropy, ");
sb.append("Entropy, ");
sb.append("Difference Variance, ");
sb.append("Difference Entropy, ");
sb.append("Information Measures of Correlation, ");
sb.append("Information Measures of Correlation, ");
sb.append("Maximum Correlation COefficient");
return sb.toString();
}
private void process(ByteProcessor image) {
features = new double[14];
firePropertyChange(new Progress(1, "creating coocurrence matrix"));
Coocurrence coocurrence = new Coocurrence(image, NUM_GRAY_VALUES, this.haralickDist);
double[][] cooccurrenceMatrix = coocurrence.getCooccurrenceMatrix();
double meanGrayValue = coocurrence.getMeanGrayValue();
firePropertyChange(new Progress(25, "normalizing"));
normalize(cooccurrenceMatrix, coocurrence.getCooccurenceSums());
firePropertyChange(new Progress(50, "computing statistics"));
calculateStatistics(cooccurrenceMatrix);
firePropertyChange(new Progress(75, "computing features"));
double[][] p = cooccurrenceMatrix;
double[][] Q = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
double sum_j_p_x_minus_y = 0;
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = p[i][j];
sum_j_p_x_minus_y += j * p_x_minus_y[j];
features[0] += p_ij * p_ij;
features[2] += i * j * p_ij - mu_x * mu_y;
features[3] += (i - meanGrayValue) * (i - meanGrayValue) * p_ij;
features[4] += p_ij / (1 + (i - j) * (i - j));
features[8] += p_ij * log(p_ij);
// feature 13
if (p_ij != 0 && p_x[i] != 0) { // would result in 0
for (int k = 0; k < NUM_GRAY_VALUES; k++) {
if (p_y[k] != 0 && p[j][k] != 0) { // would result in NaN
Q[i][j] += (p_ij * p[j][k]) / (p_x[i] * p_y[k]);
}
}
}
}
features[1] += i * i * p_x_minus_y[i];
features[9] += (i - sum_j_p_x_minus_y) * (i - sum_j_p_x_minus_y) * p_x_minus_y[i];
features[10] += p_x_minus_y[i] * log(p_x_minus_y[i]);
}
// feature 13: Max Correlation Coefficient
double[] realEigenvaluesOfQ = new Matrix(Q).eig().getRealEigenvalues();
Arrays2.abs(realEigenvaluesOfQ);
Arrays.sort(realEigenvaluesOfQ);
features[13] = Math.sqrt(realEigenvaluesOfQ[realEigenvaluesOfQ.length - 2]);
features[2] /= Math.sqrt(var_x * var_y);
features[8] *= -1;
features[10] *= -1;
double maxhxhy = Math.max(hx, hy);
if (Math.signum(maxhxhy) == 0) {
features[11] = 0;
} else {
features[11] = (features[8] - hxy1) / maxhxhy;
}
features[12] = Math.sqrt(1 - Math.exp(-2 * (hxy2 - features[8])));
for (int i = 0; i < 2 * NUM_GRAY_VALUES - 1; i++) {
features[5] += i * p_x_plus_y[i];
features[7] += p_x_plus_y[i] * log(p_x_plus_y[i]);
double sum_j_p_x_plus_y = 0;
for (int j = 0; j < 2 * NUM_GRAY_VALUES - 1; j++) {
sum_j_p_x_plus_y += j * p_x_plus_y[j];
}
features[6] += (i - sum_j_p_x_plus_y) * (i - sum_j_p_x_plus_y) * p_x_plus_y[i];
}
features[7] *= -1;
}
/**
* Calculates the statistical properties.
*/
private void calculateStatistics(double[][] cooccurrenceMatrix) {
// p_x, p_y, p_x+y, p_x-y
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
p_x[i] += p_ij;
p_y[j] += p_ij;
p_x_plus_y[i + j] += p_ij;
p_x_minus_y[Math.abs(i - j)] += p_ij;
}
}
// mean and variance values
double[] meanVar;
meanVar = meanVar(p_x);
mu_x = meanVar[0];
var_x = meanVar[1];
meanVar = meanVar(p_y);
mu_y = meanVar[0];
var_y = meanVar[1];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
// hx and hy
hx += p_x[i] * log(p_x[i]);
hy += p_y[i] * log(p_y[i]);
// hxy1 and hxy2
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
hxy1 += p_ij * log(p_x[i] * p_y[j]);
hxy2 += p_x[i] * p_y[j] * log(p_x[i] * p_y[j]);
}
}
hx *= -1;
hy *= -1;
hxy1 *= -1;
hxy2 *= -1;
}
/**
* Compute mean and variance of the given array
*
* #param a inut values
* #return array{mean, variance}
*/
private double[] meanVar(double[] a) {
// VAR(X) = E(X^2) - E(X)^2
double ex = 0, ex2 = 0; // E(X), E(X^2)
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
ex += a[i];
ex2 += a[i] * a[i];
}
ex /= a.length;
ex2 /= a.length;
double var = ex2 - ex * ex;
return new double[]{ex, var};
}
/**
* Returns the logarithm of the specified value.
*
* #param value the value for which the logarithm should be returned
* #return the logarithm of the specified value
*/
private double log(double value) {
double log = Math.log(value);
if (log == Double.NEGATIVE_INFINITY) {
log = 0;
}
return log;
}
private void normalize(double[][] A, double sum) {
for (int i = 0; i < A.length; i++) {
Arrays2.div(A[i], sum);
}
}
//<editor-fold defaultstate="collapsed" desc="getter/Setter">
/**
* Getter for haralick distributions
*
* #return haralick distributions
*/
public int getHaralickDist() {
return haralickDist;
}
/**
* Setter for haralick distributions
*
* #param haralickDist int for haralick distributions
*/
public void setHaralickDist(int haralickDist) {
this.haralickDist = haralickDist;
}
//</editor-fold>
}
//<editor-fold defaultstate="collapsed" desc="Coocurrence Matrix">
/**
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
*/
class Coocurrence {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES;
/**
* The number of gray levels in an image
*/
private final int GRAY_RANGES = 256;
/**
* The scale for the gray values for conversion rgb to gray values.
*/
private final double GRAY_SCALE;
/**
* gray histogram of the image.
*/
private final double[] grayHistogram;
/**
* quantized gray values of each pixel of the image.
*/
private final byte[] grayValue;
/**
* mean gray value
*/
private double meanGrayValue = 0;
/**
* The cooccurrence matrix
*/
private final double[][] cooccurrenceMatrices;
/**
* The value for one increment in the gray/color histograms.
*/
private final int HARALICK_DIST;
private final ByteProcessor image;
public Coocurrence(ByteProcessor b, int numGrayValues, int haralickDist) {
this.NUM_GRAY_VALUES = numGrayValues;
this.image = b;
this.GRAY_SCALE = (double) GRAY_RANGES / (double) NUM_GRAY_VALUES;
this.cooccurrenceMatrices = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
this.grayValue = new byte[image.getPixelCount()];
this.grayHistogram = new double[GRAY_RANGES];
this.HARALICK_DIST = haralickDist;
calculate();
}
public double getMeanGrayValue() {
return this.meanGrayValue;
}
public double[][] getCooccurrenceMatrix() {
return this.cooccurrenceMatrices;
}
public double getCooccurenceSums() {
return image.getPixelCount() * 8;
}
private void calculate() {
calculateGreyValues();
final int imageWidth = image.getWidth();
final int imageHeight = image.getHeight();
final int d = HARALICK_DIST;
int i, j, pos;
// image is not empty per default
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
pos = imageWidth * y + x;
// horizontal neighbor: 0 degrees
i = x - d;
// j = y;
if (!(i < 0)) {
increment(grayValue[pos], grayValue[pos - d]);
}
// vertical neighbor: 90 degree
// i = x;
j = y - d;
if (!(j < 0)) {
increment(grayValue[pos], grayValue[pos - d * imageWidth]);
}
// 45 degree diagonal neigbor
i = x + d;
j = y - d;
if (i < imageWidth && !(j < 0)) {
increment(grayValue[pos], grayValue[pos + d - d * imageWidth]);
}
// 135 vertical neighbor
i = x - d;
j = y - d;
if (!(i < 0) && !(j < 0)) {
increment(grayValue[pos], grayValue[pos - d - d * imageWidth]);
}
}
}
meanGrayValue = Arrays2.sum(grayValue);
}
private void calculateGreyValues() {
int size = image.getPixelCount();
int gray;
for (int pos = 0; pos < size; pos++) {
gray = image.get(pos);
grayValue[pos] = (byte) (gray / GRAY_SCALE); // quantized for texture analysis
grayHistogram[gray]++;
}
Arrays2.div(grayHistogram, size);
}
/**
* Incremets the coocurrence matrix at the specified positions (g1,g2) and
* (g2,g1).
*
* #param g1 the gray value of the first pixel
* #param g2 the gray value of the second pixel
*/
private void increment(int g1, int g2) {
cooccurrenceMatrices[g1][g2]++;
cooccurrenceMatrices[g2][g1]++;
}
}
//</editor-fold>
Here you have the source.
Thanks in advance=)

Implementation of the Riemann Siegel Formula in Java, curious about improving the remainder term

I wrote a basic program which calculates the Riemann-Siegel Z(t) function. I was curious if there is a better way to approximate the remainder term. The method I have now uses the awful table approximations from Haselgrove.
Further information about the Riemann Siegel formula. This might be a tad bit advanced, although further details of this are found in this thesis. Also, in Edwards book.
I know that my for loop is not optimal, I was just using it for testing purposes. I can use a different method to approximate zeroes.
Here is the implementation that I wrote:
import java.util.*;
public class Main {
public static void main(String[] args) {
double s[] = new double[10];
s[0] = 2;
for (double i = 0; i < 500; i += 0.0001) {
if (RiemennZ(i, 4) < 0.0001 && RiemennZ(i, 4) > -1*0.0001)
System.out.println("Found a zero at " + i + ", the value of Zeta(s) is "
+ RiemennZ(i, 4));
}
//System.out.println(4);
//System.out.println("Value of the Zeta Function " + Arrays.toString(Riemann.zeta(s)));
System.out.println("The function you wrote is- " + RiemennZ(16, 4));
System.out.println(fAbs(1.3) -1.0);
//System.out.println(theta(25));
}
// Riemann-Siegel theta function using the approximation by the Stirling series
public static double theta (double t) {
return (t/2.0 * Math.log(t/(2.0*Math.PI)) - t/2.0 - Math.PI/8.0
+ 1.0/(48.0*Math.pow(t, 1)) + 7.0/(5760*Math.pow(t, 3)));
}
// Computes Math.Floor of the absolute value term passed in as t.
public static double fAbs(double t) {
return Math.floor(Math.abs(t));
}
// Riemann-Siegel Z(t) function implemented per the Riemenn Siegel formula.
// See http://mathworld.wolfram.com/Riemann-SiegelFormula.html for details
public static double RiemennZ(double t, int r) {
double twopi = Math.PI * 2.0;
double val = Math.sqrt(t/twopi);
double n = fAbs(val);
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += (Math.cos(theta(t) - t * Math.log(i))) / Math.sqrt(i);
}
sum = 2.0 * sum;
// Add the remainder terms
double remainder;
double frac = val - n;
int k = 0;
double R = 0.0;
while (k <= r) {
R = R + C(k, 2.0*frac-1.0) * Math.pow(t / twopi, ((double) k) * -0.5);
k++;
}
remainder = Math.pow(-1, (int)n-1) * Math.pow(t / twopi, -0.25) * R;
return sum + remainder;
}
// C terms for the Riemann-Siegel formula
public static double C (int n, double z) {
if (n==0)
return(.38268343236508977173 * Math.pow(z, 0.0)
+.43724046807752044936 * Math.pow(z, 2.0)
+.13237657548034352332 * Math.pow(z, 4.0)
-.01360502604767418865 * Math.pow(z, 6.0)
-.01356762197010358089 * Math.pow(z, 8.0)
-.00162372532314446528 * Math.pow(z,10.0)
+.00029705353733379691 * Math.pow(z,12.0)
+.00007943300879521470 * Math.pow(z,14.0)
+.00000046556124614505 * Math.pow(z,16.0)
-.00000143272516309551 * Math.pow(z,18.0)
-.00000010354847112313 * Math.pow(z,20.0)
+.00000001235792708386 * Math.pow(z,22.0)
+.00000000178810838580 * Math.pow(z,24.0)
-.00000000003391414390 * Math.pow(z,26.0)
-.00000000001632663390 * Math.pow(z,28.0)
-.00000000000037851093 * Math.pow(z,30.0)
+.00000000000009327423 * Math.pow(z,32.0)
+.00000000000000522184 * Math.pow(z,34.0)
-.00000000000000033507 * Math.pow(z,36.0)
-.00000000000000003412 * Math.pow(z,38.0)
+.00000000000000000058 * Math.pow(z,40.0)
+.00000000000000000015 * Math.pow(z,42.0));
else if (n==1)
return(-.02682510262837534703 * Math.pow(z, 1.0)
+.01378477342635185305 * Math.pow(z, 3.0)
+.03849125048223508223 * Math.pow(z, 5.0)
+.00987106629906207647 * Math.pow(z, 7.0)
-.00331075976085840433 * Math.pow(z, 9.0)
-.00146478085779541508 * Math.pow(z,11.0)
-.00001320794062487696 * Math.pow(z,13.0)
+.00005922748701847141 * Math.pow(z,15.0)
+.00000598024258537345 * Math.pow(z,17.0)
-.00000096413224561698 * Math.pow(z,19.0)
-.00000018334733722714 * Math.pow(z,21.0)
+.00000000446708756272 * Math.pow(z,23.0)
+.00000000270963508218 * Math.pow(z,25.0)
+.00000000007785288654 * Math.pow(z,27.0)
-.00000000002343762601 * Math.pow(z,29.0)
-.00000000000158301728 * Math.pow(z,31.0)
+.00000000000012119942 * Math.pow(z,33.0)
+.00000000000001458378 * Math.pow(z,35.0)
-.00000000000000028786 * Math.pow(z,37.0)
-.00000000000000008663 * Math.pow(z,39.0)
-.00000000000000000084 * Math.pow(z,41.0)
+.00000000000000000036 * Math.pow(z,43.0)
+.00000000000000000001 * Math.pow(z,45.0));
else if (n==2)
return(+.00518854283029316849 * Math.pow(z, 0.0)
+.00030946583880634746 * Math.pow(z, 2.0)
-.01133594107822937338 * Math.pow(z, 4.0)
+.00223304574195814477 * Math.pow(z, 6.0)
+.00519663740886233021 * Math.pow(z, 8.0)
+.00034399144076208337 * Math.pow(z,10.0)
-.00059106484274705828 * Math.pow(z,12.0)
-.00010229972547935857 * Math.pow(z,14.0)
+.00002088839221699276 * Math.pow(z,16.0)
+.00000592766549309654 * Math.pow(z,18.0)
-.00000016423838362436 * Math.pow(z,20.0)
-.00000015161199700941 * Math.pow(z,22.0)
-.00000000590780369821 * Math.pow(z,24.0)
+.00000000209115148595 * Math.pow(z,26.0)
+.00000000017815649583 * Math.pow(z,28.0)
-.00000000001616407246 * Math.pow(z,30.0)
-.00000000000238069625 * Math.pow(z,32.0)
+.00000000000005398265 * Math.pow(z,34.0)
+.00000000000001975014 * Math.pow(z,36.0)
+.00000000000000023333 * Math.pow(z,38.0)
-.00000000000000011188 * Math.pow(z,40.0)
-.00000000000000000416 * Math.pow(z,42.0)
+.00000000000000000044 * Math.pow(z,44.0)
+.00000000000000000003 * Math.pow(z,46.0));
else if (n==3)
return(-.00133971609071945690 * Math.pow(z, 1.0)
+.00374421513637939370 * Math.pow(z, 3.0)
-.00133031789193214681 * Math.pow(z, 5.0)
-.00226546607654717871 * Math.pow(z, 7.0)
+.00095484999985067304 * Math.pow(z, 9.0)
+.00060100384589636039 * Math.pow(z,11.0)
-.00010128858286776622 * Math.pow(z,13.0)
-.00006865733449299826 * Math.pow(z,15.0)
+.00000059853667915386 * Math.pow(z,17.0)
+.00000333165985123995 * Math.pow(z,19.0)
+.00000021919289102435 * Math.pow(z,21.0)
-.00000007890884245681 * Math.pow(z,23.0)
-.00000000941468508130 * Math.pow(z,25.0)
+.00000000095701162109 * Math.pow(z,27.0)
+.00000000018763137453 * Math.pow(z,29.0)
-.00000000000443783768 * Math.pow(z,31.0)
-.00000000000224267385 * Math.pow(z,33.0)
-.00000000000003627687 * Math.pow(z,35.0)
+.00000000000001763981 * Math.pow(z,37.0)
+.00000000000000079608 * Math.pow(z,39.0)
-.00000000000000009420 * Math.pow(z,41.0)
-.00000000000000000713 * Math.pow(z,43.0)
+.00000000000000000033 * Math.pow(z,45.0)
+.00000000000000000004 * Math.pow(z,47.0));
else
return(+.00046483389361763382 * Math.pow(z, 0.0)
-.00100566073653404708 * Math.pow(z, 2.0)
+.00024044856573725793 * Math.pow(z, 4.0)
+.00102830861497023219 * Math.pow(z, 6.0)
-.00076578610717556442 * Math.pow(z, 8.0)
-.00020365286803084818 * Math.pow(z,10.0)
+.00023212290491068728 * Math.pow(z,12.0)
+.00003260214424386520 * Math.pow(z,14.0)
-.00002557906251794953 * Math.pow(z,16.0)
-.00000410746443891574 * Math.pow(z,18.0)
+.00000117811136403713 * Math.pow(z,20.0)
+.00000024456561422485 * Math.pow(z,22.0)
-.00000002391582476734 * Math.pow(z,24.0)
-.00000000750521420704 * Math.pow(z,26.0)
+.00000000013312279416 * Math.pow(z,28.0)
+.00000000013440626754 * Math.pow(z,30.0)
+.00000000000351377004 * Math.pow(z,32.0)
-.00000000000151915445 * Math.pow(z,34.0)
-.00000000000008915418 * Math.pow(z,36.0)
+.00000000000001119589 * Math.pow(z,38.0)
+.00000000000000105160 * Math.pow(z,40.0)
-.00000000000000005179 * Math.pow(z,42.0)
-.00000000000000000807 * Math.pow(z,44.0)
+.00000000000000000011 * Math.pow(z,46.0)
+.00000000000000000004 * Math.pow(z,48.0));
}
}
The remainder terms are defined by: (cos[2pi(p^2-p-1/(16))])/(cos(2pip))
Doing multiple derivatives of this function inside Wolfram Alpha is a complete mess. Has anyone ever experienced this sort of problem before?
In order to use multiple remainder terms, I need to compute multiple derivatives for: (cos[2pi(p^2-p-1/(16))])/(cos(2pip))
Is there some way around this that can be implemented in Java?
One way is by using finite difference methods. This is not a very good solution but is the first thing that I thought about.
// Derivation of the first C term using first order central difference
public static double firstDerivative(double p) {
double epsilon = 0.0000000001;
double d1, d2;
double dx = 0.00001;
double diff = 1.0;
d1 = (function(p + dx) - function(p - dx)) / (2 * dx);
while (diff > epsilon) {
dx /= 2;
d2 = (function(p + dx) - function(p - dx)) / (2 * dx);
diff = Math.abs(d2 - d1);
d1 = d2;
}
return d1;
}
// Derivation of the second C term using second order central difference
public static double secondDerivative(double p) {
double epsilon = 0.0000000001;
double d1, d2;
double dx = 0.00001;
double diff = 1.0;
d1 = (function(p + dx) - 2.0 * function(p) + function(p - dx)) / Math.pow(dx, 2);
while (diff > epsilon) {
dx /= 2;
d2 = (function(p + dx) - 2.0 * function(p) + function(p - dx)) / Math.pow(dx, 2);
diff = Math.abs(d2 - d1);
d1 = d2;
}
return d1;
}
How many derivatives do you need?
Do you want to pre-calculate them or do them "on-the-fly"?
You can use GeoGebra (in Java) easily to pre-calculate them, eg
CopyFreeObject[Derivative[cos(2π (x² - x - 1 / 16)) / cos(2π x), 3]]
If you want to delve a bit more, internally GeoGebra can either use the Giac CAS engine (in C++) to do derivatives, or it can calculate them directly, see ExpressionNode.derivative()

Categories