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));
}
}
Related
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;
}
}
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.
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
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()
Does Java have a class for complex numbers?
There's an Apache Commons one called Complex. I don't believe the JDK has one.
No, the JDK does not have one but here is an implementation I have written.
Here is the GITHUB project.
/**
* <code>ComplexNumber</code> is a class which implements complex numbers in Java.
* It includes basic operations that can be performed on complex numbers such as,
* addition, subtraction, multiplication, conjugate, modulus and squaring.
* The data type for Complex Numbers.
* <br /><br />
* The features of this library include:<br />
* <ul>
* <li>Arithmetic Operations (addition, subtraction, multiplication, division)</li>
* <li>Complex Specific Operations - Conjugate, Inverse, Absolute/Magnitude, Argument/Phase</li>
* <li>Trigonometric Operations - sin, cos, tan, cot, sec, cosec</li>
* <li>Mathematical Functions - exp</li>
* <li>Complex Parsing of type x+yi</li>
* </ul>
*
* #author Abdul Fatir
* #version 1.1
*
*/
public class ComplexNumber
{
/**
* Used in <code>format(int)</code> to format the complex number as x+yi
*/
public static final int XY = 0;
/**
* Used in <code>format(int)</code> to format the complex number as R.cis(theta), where theta is arg(z)
*/
public static final int RCIS = 1;
/**
* The real, Re(z), part of the <code>ComplexNumber</code>.
*/
private double real;
/**
* The imaginary, Im(z), part of the <code>ComplexNumber</code>.
*/
private double imaginary;
/**
* Constructs a new <code>ComplexNumber</code> object with both real and imaginary parts 0 (z = 0 + 0i).
*/
public ComplexNumber()
{
real = 0.0;
imaginary = 0.0;
}
/**
* Constructs a new <code>ComplexNumber</code> object.
* #param real the real part, Re(z), of the complex number
* #param imaginary the imaginary part, Im(z), of the complex number
*/
public ComplexNumber(double real, double imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
/**
* Adds another <code>ComplexNumber</code> to the current complex number.
* #param z the complex number to be added to the current complex number
*/
public void add(ComplexNumber z)
{
set(add(this,z));
}
/**
* Subtracts another <code>ComplexNumber</code> from the current complex number.
* #param z the complex number to be subtracted from the current complex number
*/
public void subtract(ComplexNumber z)
{
set(subtract(this,z));
}
/**
* Multiplies another <code>ComplexNumber</code> to the current complex number.
* #param z the complex number to be multiplied to the current complex number
*/
public void multiply(ComplexNumber z)
{
set(multiply(this,z));
}
/**
* Divides the current <code>ComplexNumber</code> by another <code>ComplexNumber</code>.
* #param z the divisor
*/
public void divide(ComplexNumber z)
{
set(divide(this,z));
}
/**
* Sets the value of current complex number to the passed complex number.
* #param z the complex number
*/
public void set(ComplexNumber z)
{
this.real = z.real;
this.imaginary = z.imaginary;
}
/**
* Adds two <code>ComplexNumber</code>.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 + z2).
*/
public static ComplexNumber add(ComplexNumber z1, ComplexNumber z2)
{
return new ComplexNumber(z1.real + z2.real, z1.imaginary + z2.imaginary);
}
/**
* Subtracts one <code>ComplexNumber</code> from another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 - z2).
*/
public static ComplexNumber subtract(ComplexNumber z1, ComplexNumber z2)
{
return new ComplexNumber(z1.real - z2.real, z1.imaginary - z2.imaginary);
}
/**
* Multiplies one <code>ComplexNumber</code> to another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 * z2).
*/
public static ComplexNumber multiply(ComplexNumber z1, ComplexNumber z2)
{
double _real = z1.real*z2.real - z1.imaginary*z2.imaginary;
double _imaginary = z1.real*z2.imaginary + z1.imaginary*z2.real;
return new ComplexNumber(_real,_imaginary);
}
/**
* Divides one <code>ComplexNumber</code> by another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 / z2).
*/
public static ComplexNumber divide(ComplexNumber z1, ComplexNumber z2)
{
ComplexNumber output = multiply(z1,z2.conjugate());
double div = Math.pow(z2.mod(),2);
return new ComplexNumber(output.real/div,output.imaginary/div);
}
/**
* The complex conjugate of the current complex number.
* #return a <code>ComplexNumber</code> object which is the conjugate of the current complex number
*/
public ComplexNumber conjugate()
{
return new ComplexNumber(this.real,-this.imaginary);
}
/**
* The modulus, magnitude or the absolute value of current complex number.
* #return the magnitude or modulus of current complex number
*/
public double mod()
{
return Math.sqrt(Math.pow(this.real,2) + Math.pow(this.imaginary,2));
}
/**
* The square of the current complex number.
* #return a <code>ComplexNumber</code> which is the square of the current complex number.
*/
public ComplexNumber square()
{
double _real = this.real*this.real - this.imaginary*this.imaginary;
double _imaginary = 2*this.real*this.imaginary;
return new ComplexNumber(_real,_imaginary);
}
/**
* #return the complex number in x + yi format
*/
#Override
public String toString()
{
String re = this.real+"";
String im = "";
if(this.imaginary < 0)
im = this.imaginary+"i";
else
im = "+"+this.imaginary+"i";
return re+im;
}
/**
* Calculates the exponential of the <code>ComplexNumber</code>
* #param z The input complex number
* #return a <code>ComplexNumber</code> which is e^(input z)
*/
public static ComplexNumber exp(ComplexNumber z)
{
double a = z.real;
double b = z.imaginary;
double r = Math.exp(a);
a = r*Math.cos(b);
b = r*Math.sin(b);
return new ComplexNumber(a,b);
}
/**
* Calculates the <code>ComplexNumber</code> to the passed integer power.
* #param z The input complex number
* #param power The power.
* #return a <code>ComplexNumber</code> which is (z)^power
*/
public static ComplexNumber pow(ComplexNumber z, int power)
{
ComplexNumber output = new ComplexNumber(z.getRe(),z.getIm());
for(int i = 1; i < power; i++)
{
double _real = output.real*z.real - output.imaginary*z.imaginary;
double _imaginary = output.real*z.imaginary + output.imaginary*z.real;
output = new ComplexNumber(_real,_imaginary);
}
return output;
}
/**
* Calculates the sine of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the sine of z.
*/
public static ComplexNumber sin(ComplexNumber z)
{
double x = Math.exp(z.imaginary);
double x_inv = 1/x;
double r = Math.sin(z.real) * (x + x_inv)/2;
double i = Math.cos(z.real) * (x - x_inv)/2;
return new ComplexNumber(r,i);
}
/**
* Calculates the cosine of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the cosine of z.
*/
public static ComplexNumber cos(ComplexNumber z)
{
double x = Math.exp(z.imaginary);
double x_inv = 1/x;
double r = Math.cos(z.real) * (x + x_inv)/2;
double i = -Math.sin(z.real) * (x - x_inv)/2;
return new ComplexNumber(r,i);
}
/**
* Calculates the tangent of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the tangent of z.
*/
public static ComplexNumber tan(ComplexNumber z)
{
return divide(sin(z),cos(z));
}
/**
* Calculates the co-tangent of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the co-tangent of z.
*/
public static ComplexNumber cot(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),tan(z));
}
/**
* Calculates the secant of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the secant of z.
*/
public static ComplexNumber sec(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),cos(z));
}
/**
* Calculates the co-secant of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the co-secant of z.
*/
public static ComplexNumber cosec(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),sin(z));
}
/**
* The real part of <code>ComplexNumber</code>
* #return the real part of the complex number
*/
public double getRe()
{
return this.real;
}
/**
* The imaginary part of <code>ComplexNumber</code>
* #return the imaginary part of the complex number
*/
public double getIm()
{
return this.imaginary;
}
/**
* The argument/phase of the current complex number.
* #return arg(z) - the argument of current complex number
*/
public double getArg()
{
return Math.atan2(imaginary,real);
}
/**
* Parses the <code>String</code> as a <code>ComplexNumber</code> of type x+yi.
* #param s the input complex number as string
* #return a <code>ComplexNumber</code> which is represented by the string.
*/
public static ComplexNumber parseComplex(String s)
{
s = s.replaceAll(" ","");
ComplexNumber parsed = null;
if(s.contains(String.valueOf("+")) || (s.contains(String.valueOf("-")) && s.lastIndexOf('-') > 0))
{
String re = "";
String im = "";
s = s.replaceAll("i","");
s = s.replaceAll("I","");
if(s.indexOf('+') > 0)
{
re = s.substring(0,s.indexOf('+'));
im = s.substring(s.indexOf('+')+1,s.length());
parsed = new ComplexNumber(Double.parseDouble(re),Double.parseDouble(im));
}
else if(s.lastIndexOf('-') > 0)
{
re = s.substring(0,s.lastIndexOf('-'));
im = s.substring(s.lastIndexOf('-')+1,s.length());
parsed = new ComplexNumber(Double.parseDouble(re),-Double.parseDouble(im));
}
}
else
{
// Pure imaginary number
if(s.endsWith("i") || s.endsWith("I"))
{
s = s.replaceAll("i","");
s = s.replaceAll("I","");
parsed = new ComplexNumber(0, Double.parseDouble(s));
}
// Pure real number
else
{
parsed = new ComplexNumber(Double.parseDouble(s),0);
}
}
return parsed;
}
/**
* Checks if the passed <code>ComplexNumber</code> is equal to the current.
* #param z the complex number to be checked
* #return true if they are equal, false otherwise
*/
#Override
public final boolean equals(Object z)
{
if (!(z instanceof ComplexNumber))
return false;
ComplexNumber a = (ComplexNumber) z;
return (real == a.real) && (imaginary == a.imaginary);
}
/**
* The inverse/reciprocal of the complex number.
* #return the reciprocal of current complex number.
*/
public ComplexNumber inverse()
{
return divide(new ComplexNumber(1,0),this);
}
/**
* Formats the Complex number as x+yi or r.cis(theta)
* #param format_id the format ID <code>ComplexNumber.XY</code> or <code>ComplexNumber.RCIS</code>.
* #return a string representation of the complex number
* #throws IllegalArgumentException if the format_id does not match.
*/
public String format(int format_id) throws IllegalArgumentException
{
String out = "";
if(format_id == XY)
out = toString();
else if(format_id == RCIS)
{
out = mod()+" cis("+getArg()+")";
}
else
{
throw new IllegalArgumentException("Unknown Complex Number format.");
}
return out;
}
}
The JDK doesn't current have any classes for complex numbers, unfortunately.
You could have a look at:
http://www.java2s.com/Code/Java/Data-Type/Thisclassrepresentscomplexnumbersanddefinesmethodsforperformingarithmeticoncomplexnumbers.htm
which provides an implementation you may find useful.