Complex number addition in Java - java

I been trying to figure out how to set up this equation to add two complex numbers for Java.
There's two methods, but I don't understand exactly what the first one is asking me to do. Is it saying I need to do (real1 + imag1) instead of (real1 + real2)? If that is the case then how would I get that result to go into c1? I also am having trouble with the second method result to hold the sum and return it.
/*Method for adding the real and imaginary parts of two complex numbers,
*which returns the result in a new complex number
*/
public static ComplexNumber addComplexNumbers(double real1, double imag1, double real2, double imag2){
ComplexNumber result = ComplexNumber.addComplexNumbers(real1, imag1, real2, imag2);
result.setReal(real1 + real2);
result.setImag(imag1 + imag2);
return result;
}
//Method for adding two complex numbers
public static ComplexNumber addComplexNumbers(ComplexNumber c1, ComplexNumber c2){
ComplexNumber result = new ComplexNumber();
result = (c1.real + c2.real) + (c1.imag + c2.imag);
}

final public class Complex {
private final double real;
private final double imag;
public Complex() {
this(0.0, 0.0);
}
public Complex(double r) {
this(r, 0.0);
}
public Complex(double r, double i) {
this.real = r;
this.imag = i;
}
public Complex add(Complex addend) {
return new Complex((this.real + addend.real), (this.imag + addend.imag));
}
}

Though this already been answered I thought people may benefit by the following class which does a lot of functions related to Complex Numbers.
This has been released under MIT License and the GitHub project is here.
/**
* <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;
}
}

Check out this simple program .
class Com{
int real,img;
Com (int r, int i){
real = r;
img = i;
}
void add(Com c){
real = real + c.real;
img = img + c.img;
}
void print(){
System.out.println(real+" +i"+img);
}
}
public class complex {
public static void main(String [] args){
Com c1 = new Com(10,20);
c1.print();
Com c2 = new Com(20,10);
c1.add(c2);
c1.print();
}
}

Related

Given a set of points in 3d space, find all sets of points within a distance of eachother

I have a set of 3d points S.
I need to find the set X of all sets of points in S which are within manhattan distance d of each other.
i.e. for each set Y in X there exists atleast one point in 3d space that is within distance d of all points in Y
The length of set S will never be >20 but I will have to run this analysis on a stream of sets which are being produced at ~10 new sets per second, so whatever solution I use will have to be fairly efficient.
an example to help visualize the problem, given the following:
the output would be ((A,B), (B,C,E), (B,D,E))
we only care about the largest possible sets so the sets (B,C), (B,D), (B,E), (C,E) and (D,E), while within the given parameters, are not in the output given they are subsets of other sets in X
also this I'm doing this in java but any pointers in terms of algorithms or pseudo code would be greatly appreciated, thanks in advance.
A solution in pseudocode would be:
calculate_intersections(areas):
intersections = calculate every two intersecting areas
combinations = combine_intersections(intersections)
reduced = remove all sets in combinations that are included in bigger sets
combine_intersections(intersections):
do:
combinations = new HashSet
for s1 in intersections:
for s2 in intersections:
diff_1_2 = s1 \ s2
diff_2_1 = s2 \ s1
if diff_1_2.len == 1 && diff_2_1.len == 1:
union = diff_1_2 + diff_2_1
if union in intersections:
union2 = s1 + s2
if !union2 in intersections:
combinations.add(union)
while (combinations not empty)
An implementation in Java could look like this:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.collections4.SetUtils;
public class IntersectionSetCalculation {
private static class ManhattanDistanceArea {
private String id;
private Vector3D center;
private double distance;
public ManhattanDistanceArea(Vector3D center, double distance, String id) {
this.center = center;
this.distance = distance;
this.id = id;
}
#Override
public String toString() {
return id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((center == null) ? 0 : center.hashCode());
long temp;
temp = Double.doubleToLongBits(distance);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManhattanDistanceArea other = (ManhattanDistanceArea) obj;
if (center == null) {
if (other.center != null)
return false;
}
else if (!center.equals(other.center))
return false;
if (Double.doubleToLongBits(distance) != Double.doubleToLongBits(other.distance))
return false;
if (id == null) {
if (other.id != null)
return false;
}
else if (!id.equals(other.id))
return false;
return true;
}
public boolean intersects(ManhattanDistanceArea other) {
double maxDist = distance + other.distance;
return center.distance(other.center, 1) < maxDist;
}
}
/**
* Calculate the intersection of all areas (maximum of 2 areas in an intersection)
*/
public static Set<Set<ManhattanDistanceArea>> getIntersectingAreas(Set<ManhattanDistanceArea> areas) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>();
for (ManhattanDistanceArea area : areas) {
for (ManhattanDistanceArea area2 : areas) {
if (!area.equals(area2) && area.intersects(area2)) {
HashSet<ManhattanDistanceArea> intersection = new HashSet<ManhattanDistanceArea>();
intersection.add(area);
intersection.add(area2);
intersections.add(intersection);
}
}
}
Set<Set<ManhattanDistanceArea>> combined = combineIntersections(intersections);
Set<Set<ManhattanDistanceArea>> reduced = reduceIntersections(combined);
return reduced;
}
/**
* Combine the small intersections (with a maximum of 2 areas in an intersection) to bigger intersections
*/
public static Set<Set<ManhattanDistanceArea>> combineIntersections(Set<Set<ManhattanDistanceArea>> inters) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>(inters);
Set<Set<ManhattanDistanceArea>> combinations;
do {
combinations = new HashSet<Set<ManhattanDistanceArea>>();
for (Set<ManhattanDistanceArea> intersecting1 : intersections) {
for (Set<ManhattanDistanceArea> intersecting2 : intersections) {
Set<ManhattanDistanceArea> diff_1_2 = SetUtils.difference(intersecting1, intersecting2);
Set<ManhattanDistanceArea> diff_2_1 = SetUtils.difference(intersecting2, intersecting1);
if (diff_1_2.size() == 1 && diff_2_1.size() == 1) {
Set<ManhattanDistanceArea> union_1_2 = SetUtils.union(diff_1_2, diff_2_1);
if (intersections.contains(union_1_2)) {
Set<ManhattanDistanceArea> union = SetUtils.union(intersecting1, intersecting2);
if (!intersections.contains(union)) {
combinations.add(union);
}
}
}
}
}
intersections.addAll(combinations);
} while (!combinations.isEmpty());
return intersections;
}
/**
* Remove the small intersections that are completely covered by bigger intersections
*/
public static Set<Set<ManhattanDistanceArea>> reduceIntersections(Set<Set<ManhattanDistanceArea>> inters) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>(inters);
Iterator<Set<ManhattanDistanceArea>> iter = intersections.iterator();
while (iter.hasNext()) {
Set<ManhattanDistanceArea> intersection = iter.next();
for (Set<ManhattanDistanceArea> intersection2 : inters) {
if (intersection2.size() > intersection.size() && intersection2.containsAll(intersection)) {
iter.remove();
break;
}
}
}
return intersections;
}
public static void main(String[] args) {
final double dist = 2d;//the manhattan distance d
ManhattanDistanceArea A = new ManhattanDistanceArea(new Vector3D(0, -3, 0), dist, "A");
ManhattanDistanceArea B = new ManhattanDistanceArea(new Vector3D(0, 0, 0), dist, "B");
ManhattanDistanceArea C = new ManhattanDistanceArea(new Vector3D(3.5, 0, 0), dist, "C");
ManhattanDistanceArea D = new ManhattanDistanceArea(new Vector3D(0, 3.5, 0), dist, "D");
ManhattanDistanceArea E = new ManhattanDistanceArea(new Vector3D(1, 1, 0), dist, "E");
ManhattanDistanceArea F = new ManhattanDistanceArea(new Vector3D(-1, 1, 0), dist, "F");
//test the example you provided
Set<ManhattanDistanceArea> abcde = new HashSet<ManhattanDistanceArea>();
abcde.addAll(Arrays.asList(new ManhattanDistanceArea[] {A, B, C, D, E}));
//test another example
Set<ManhattanDistanceArea> abcdef = new HashSet<ManhattanDistanceArea>();
abcdef.addAll(abcde);
abcdef.add(F);
Set<Set<ManhattanDistanceArea>> intersectionsABCDE = getIntersectingAreas(abcde);
Set<Set<ManhattanDistanceArea>> intersectionsABCDEF = getIntersectingAreas(abcdef);
System.out.println(intersectionsABCDE);
System.out.println(intersectionsABCDEF);
//test the runntime for 1000 calculation
double startTime = System.currentTimeMillis();
final int calculations = 1000;
for (int i = 0; i < calculations; i++) {
Set<ManhattanDistanceArea> areas = new HashSet<ManhattanDistanceArea>();
for (int j = 0; j < 20; j++) {
areas.add(new ManhattanDistanceArea(new Vector3D(Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5), dist,
"A" + j));
}
getIntersectingAreas(areas);
}
System.out.println("\nTime used for " + calculations + " intersection calculations (with sets of size 20): "
+ (System.currentTimeMillis() - startTime) + "ms");
}
}
For the implementation I used this class Vector3D:
public class Vector3D {
public double x;
public double y;
public double z;
public static final Vector3D NAN_VEC = new Vector3D(Double.NaN, Double.NaN, Double.NaN);
public static final Vector3D NULL_VEC = new Vector3D(0, 0, 0);
public enum Axis {
X, Y, Z;
}
public Vector3D() {
}
/**
* Crate a new Vector2D with x and y components.
*/
public Vector3D(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3D(double... val) {
x = val[0];
y = val[1];
z = val[2];
}
/**
* Create a Vector3D by two angles (in degree).
*
* The first angle is in XY direction. The second angle is the Z direction.
*
* An angle (XY) of 0° results in (x, y) = (1, 0); 90° in (x, y) = (0, 1); ... An angle (Z) of 0° results in (x, y, z) = (x, y, 0); 90° in (x, y,
* z) = (x, y, 1); -90° in (x, y, z) = (x, y, -1)
*
* The resulting vector has a length of 1.
*
* #param angleXY
* The angle of the new vector (in degree) for the XY direction (from 0 to 360).
*
* #param angleZ
* The angle of the new vector (in degree) for the Z direction (from -90 to 90).
*/
public Vector3D(double angleXY, double angleZ) {
x = Math.cos(angleXY * Math.PI / 180) * Math.cos(angleZ * Math.PI / 180);
y = Math.sin(angleXY * Math.PI / 180) * Math.cos(angleZ * Math.PI / 180);
z = Math.sin(angleZ * Math.PI / 180);
double len = length();
x /= len;
y /= len;
z /= len;
}
private Vector3D(Vector3D clone) {
this.x = clone.x;
this.y = clone.y;
}
#Override
public Vector3D clone() {
return new Vector3D(this);
}
#Override
public String toString() {
return "Vector3D[x: " + x + " y: " + y + " z:" + z + "]";
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Vector3D) {
Vector3D v = (Vector3D) obj;
return Math.abs(x - v.x) < 1e-8 && Math.abs(y - v.y) < 1e-8 && Math.abs(z - v.z) < 1e-8;
}
return false;
}
/**
* Get this vector as 3D-Array.
*/
public double[] asArray() {
return new double[] {x, y, z};
}
/**
* The (euclidean) length of the Vector.
*/
public double length() {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
}
/**
* The length of this vector in a given norm.
*
* #param norm
* The norm of the vector length.
*
* #return The length of this vector in the given norm.
*/
public double length(int norm) {
if (norm == Integer.MAX_VALUE) {
return Math.max(Math.max(x, y), z);
}
return Math.pow(Math.pow(x, norm) + Math.pow(y, norm) + Math.pow(z, norm), 1.0 / norm);
}
/**
* Rotate this vector an angle (in degrees) around an axis resulting in a new Vector that is returned.
*
* #param degrees
* The angle to return the vector.
*
* #param axis
* The axis around which the vector is rotated.
*
* #return The new created vector.
*/
public Vector3D rotate(double degrees, Axis axis) {
double cos = Math.cos(degrees * Math.PI / 180);
double sin = Math.sin(degrees * Math.PI / 180);
switch (axis) {
case X:
return new Vector3D(x, cos * y - sin * z, sin * y + cos * z);
case Y:
return new Vector3D(cos * x + sin * z, y, -sin * x + cos * z);
case Z:
return new Vector3D(cos * x - sin * y, sin * x + cos * y, z);
default:
return null;
}
}
/**
* Project the vector given as parameter on this vector.
*
* #param vec
* The vector that is to be projected on this vector.
*
* #return The projected vector.
*/
public Vector3D project(Vector3D vec) {
return mult(scalar(vec) / Math.pow(length(), 2));
}
/**
* Add another Vector3D to this vector resulting in a new Vector that is returned.
*
* #param vec
* The vector added to this vector.
*
* #return The new created vector.
*/
public Vector3D add(Vector3D vec) {
return new Vector3D(x + vec.x, y + vec.y, z + vec.z);
}
/**
* Subtract another Vector3D from this vector resulting in a new Vector that is returned.
*
* #param vec
* The vector subtracted from this vector.
*
* #return The new created vector.
*/
public Vector3D sub(Vector3D vec) {
return new Vector3D(x - vec.x, y - vec.y, z - vec.z);
}
/**
* Multiply this vector with a scalar resulting in a new Vector that is returned.
*
* #param scalar
* The scalar to multiply this vector with.
*
* #return The new created vector.
*/
public Vector3D mult(double scalar) {
return new Vector3D(x * scalar, y * scalar, z * scalar);
}
/**
* Check whether this vector is linearly dependent to the parameter vector.
*
* #param vec
* The checked vector.
*
* #return True if the vectors are linearly dependent. False otherwise.
*/
public boolean isLinearlyDependent(Vector3D vec) {
double t1 = (x == 0 ? 0 : vec.x / x);
double t2 = (y == 0 ? 0 : vec.y / y);
double t3 = (z == 0 ? 0 : vec.z / z);
return Math.abs(t1 - t2) < 1e-5 && Math.abs(t1 - t3) < 1e-5 && t1 != 0;//all parameters t are equal and != 0
}
/**
* Calculate the scalar product of this vector and the parameter vector.
*
* #param vec
* The vector to calculate the scalar with this vector.
*
* #return The scalar of the vectors.
*/
public double scalar(Vector3D vec) {
return this.x * vec.x + this.y * vec.y + this.z * vec.z;
}
/**
* Calculate the cross product of this vector with another vector (resulting vector = this X parameter vector)
*
* #param vec
* The second vector for the cross product calculation.
*
* #return The cross product vector of the two vectors.
*/
public Vector3D cross(Vector3D vec) {
return new Vector3D(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
}
/**
* Create a new vector with the same direction but a different length as this vector.
*
* #param length
* The length of the new vector.
*
* #return The new vector with a new length.
*/
public Vector3D setLength(double length) {
double len = length();
return new Vector3D(x * length / len, y * length / len, z * length / len);
}
/**
* Get the distance of this point's position vector to another point's position vector.
*
* #param p
* The second point's position vector.
*
* #return The distance between the points.
*/
public double distance(Vector3D p) {
return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y) + (this.z - p.z) * (this.z - p.z));
}
/**
* Get the distance of this point's position vector to another point's position vector in a given norm.
*
* #param p
* The second point's position vector.
*
* #param norm
* The norm in which the distance is calculated (1 -> manhattan, 2 -> euclide, ...)
*
* #return The distance between the points in the given norm.
*/
public double distance(Vector3D p, int norm) {
return Math.pow((Math.pow(Math.abs(this.x - p.x), norm) + Math.pow(Math.abs(this.y - p.y), norm) + Math.pow(Math.abs(this.z - p.z), norm)),
1d / norm);
}
/**
* Change this vector to the new coordinates.
*/
public void move(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Move a point's position vector in a direction (by a vector) and a distance.
*
* #param p
* The direction vector.
*
* #param distance
* The distance to move the new vector
*
* #return The new created vector.
*/
public Vector3D moveTo(Vector3D p, double distance) {
double d = distance(p);
double dx = p.x - x;
double dy = p.y - y;
double dz = p.z - z;
double coef = distance / d;
return new Vector3D(x + dx * coef, y + dy * coef, z + dz * coef);
}
/**
* Get the angle difference of this vector to another vector.
*
* #param vec
* The other vector.
*
* #return The angle difference of the two vectors (from 0° to 180°).
*/
public double getAngleTo(Vector3D vec) {
double angle = Math.acos(scalar(vec) / (length() * vec.length())) * 180 / Math.PI;
if (angle > 180) {
angle = 360 - angle;
}
return angle;
}
/**
* Get the vector from this point to another.
*
* #param vec
* The point to which the vector is calculated.
*
* #return The vector from this points position vector to the other point.
*/
public Vector3D vectorTo(Vector3D vec) {
return new Vector3D(vec.x - x, vec.y - y, vec.z - z);
}
/**
* Checks whether a point (by its position vector) is in a given range of this point.
*
* #param p
* The point that is checked.
*
* #param range
* The range used for the check.
*
* #return True if the point is in the range of this point (distance <= range).
*/
public boolean isInRange(Vector3D p, double range) {
return p != this && distance(p) <= range;
}
}
and the class SetUtils from the apache commons lib.
I also added some tests:
the test from your question
another test with a bigger intersection set
a test for the runtime
The results are:
[[A, B], [B, E, C], [B, E, D]]
[[A, B], [B, E, C], [D, E, F, B]]
Time used for 1000 intersection calculations (with sets of size 20):
791.0ms
So the results seem to be correct and you can calculate more than 1000 intersections in a second.
Exhaustive distance computation between 20 points, i.e. 190 distances is nothing for a PC. Time will measure in microseconds. You can draw the desired information from the "close to" relation encoded in a matrix.

Doing a school project, can't get Area calculation right

I am working on a Java Lab for school. The purpose is to calculate the perimeter, area, and radius of circle r given a polygon with x # of sides and n length.
My Code:
public class RegularPolygon {
private int myNumSides; // # of sides
private double mySideLength; // length of side
private double myR; // radius of circumscribed circle
private double myr; //radius of inscribed circle
/**
* This is a default constructor creating a 3 sided polygon (triangle)
* This means that myNumSides should be initialized to 3
*/
public RegularPolygon() {
this.myNumSides = 3;
}
/**
* This is a parameter constructor with one int parameter and one double parameter
* #param numSides This is a parameter that sets the # of sides for object RegularPolygon
* #param sideLength This is a parameter for the length of each side in object RegularPolygon
*/
public RegularPolygon(int numSides, double sideLength) {
this.myNumSides = numSides;
this.mySideLength = sideLength;
}
/**
* Private Method to calculate the radius of the inscribed circle
* #return Nothing
*/
private void calcr() {
this.myr = 0.5 * this.getSideLength() * (1/(Math.tan(Math.PI / this.getNumside())));
}
/**
* Private Method to calculate the radius of the circumscribed circle
* #return Nothing
*/
private void calcR() {
this.myR = 1 / 2 * this.getSideLength() * (1 / (Math.sin(Math.PI / this.getNumside())));
}
/**
* This is a method that calculates the Vertex Angle. The Vertex Angle is assigned to to the variable q
* #return double Returns the double value of q, the vertex angle
*/
public double vertexAngle() {
double q = ((this.getNumside() - 2) / this.getNumside()) * Math.toRadians(180);
return q;
}
/**
* Method that calculates the perimeter of the polygon. The perimeter is assigned to the double variable perimeter
* #return double Returns the double value of the perimeter
*/
public double Perimeter() {
double perimeter = this.getSideLength() * this.getNumside();
return perimeter;
}
/**
* Method that calculates the area of the polygon RegularPolygon
* #return double Returns the double value of the area
*/
public double Area() {
double area = 1 / 2 * this.getNumside() * Math.pow(this.getR(), 2) * Math.sin(2 * Math.PI / this.getNumside());
return area;
}
/**
* Getter method that returns the value of myNumSides
* #return int Value of myNumSides
*/
public int getNumside() {
return myNumSides;
}
/**
* Getter Method that returns the value of mySideLength
* #return double Value of mySideLength
*/
public double getSideLength() {
return mySideLength;
}
/**
* Getter Method that returns the value myR
* #return double Value of circumscribed circle myR
*/
public double getR() {
return myR;
}
/**
* Getter Method that returns the value of inscribed circle myr
* #return double Value of inscribed circle myr
*/
public double getr() {
return myr;
}
}
Everything is correct except for the calcR and calcr methods. For some reason the value returned is always 0.0. Not sure if I am using the Math methods incorrectly or something.
Here is my testing code:
public class PolygonDriver {
public static void main(String[] args) {
RegularPolygon poly = new RegularPolygon(4, 10);
System.out.println(poly.Area());
System.out.println(poly.getR());
System.out.println(poly.Perimeter());
}
}
After running it, I get:
0.0
0.0
40.0
What is wrong with my methods calcR() and calcr()?
calcr() and calcR are not being called anywhere in your code so myr and myR are never being set so you are getting the initialized value of 0.0
Besides not calling calcr() and calcR(), you should change the 1/2 in Area() and the calcR() to 0.5 so that you are working with the correct data type.

can not access superclass method from within subclass that implements comparator

I am attempting to use the slopeTo method inside my slopeCompare subclass in my comparator definition. However I get an error in eclipse telling me to change slopeTo to a static method. It also does not work when I use this.slopeTo(). I thought that the whole point of subclasses was that they can use all the methods of the superclass. Can someone help me clarify what I am not understanding here? I apologize if I am misusing terminology but comparators are a new topic and I am not entirely comfortable with them.
(this is from the princeton algorithms course on udacity)
import java.util.Comparator;
import edu.princeton.cs.algs4.StdDraw;
public class Point implements Comparable<Point> {
private final int x; // x-coordinate of this point
private final int y; // y-coordinate of this point
/**
* Initializes a new point.
*
* #param x the <em>x</em>-coordinate of the point
* #param y the <em>y</em>-coordinate of the point
*/
public Point(int x, int y) {
/* DO NOT MODIFY */
this.x = x;
this.y = y;
}
/**
* Draws this point to standard draw.
*/
public void draw() {
/* DO NOT MODIFY */
StdDraw.point(x, y);
}
/**
* Draws the line segment between this point and the specified point
* to standard draw.
*
* #param that the other point
*/
public void drawTo(Point that) {
/* DO NOT MODIFY */
StdDraw.line(this.x, this.y, that.x, that.y);
}
/**
* Returns the slope between this point and the specified point.
* Formally, if the two points are (x0, y0) and (x1, y1), then the slope
* is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be
* +0.0 if the line segment connecting the two points is horizontal;
* Double.POSITIVE_INFINITY if the line segment is vertical;
* and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
*
* #param that the other point
* #return the slope between this point and the specified point
*/
public double slopeTo(Point that) {
/* YOUR CODE HERE */
if (this.compareTo(that) == 0){
return Double.NEGATIVE_INFINITY;
}
double slope = (double)(that.y-this.y)/(that.x-this.x);
return slope;
}
/**
* Compares two points by y-coordinate, breaking ties by x-coordinate.
* Formally, the invoking point (x0, y0) is less than the argument point
* (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
*
* #param that the other point
* #return the value <tt>0</tt> if this point is equal to the argument
* point (x0 = x1 and y0 = y1);
* a negative integer if this point is less than the argument
* point; and a positive integer if this point is greater than the
* argument point
*/
public int compareTo(Point that) {
if (this.y > that.y){
return 1;
}
if (this.y < that.y){
return -1;
}
if ((this.y == that.y) && (this.x < that.x)){
return -1;
}
if ((this.y == that.y) && (this.x > that.x)){
return 1;
}
else {
return 0;
}
}
/**
* Compares two points by the slope they make with this point.
* The slope is defined as in the slopeTo() method.
*
* #return the Comparator that defines this ordering on points
*/
public Comparator<Point> slopeOrder() {
/* YOUR CODE HERE */
return new SlopeCompare();
}
private static class SlopeCompare implements Comparator<Point> {
public int compare(Point a, Point b){
if (slopeTo(a) < slopeTo(b)){
return -1;
}
return 0;
}
}
/**
* Returns a string representation of this point.
* This method is provide for debugging;
* your program should not rely on the format of the string representation.
*
* #return a string representation of this point
*/
public String toString() {
/* DO NOT MODIFY */
return "(" + x + ", " + y + ")";
}
/**
* Unit tests the Point data type.
*/
public static void main(String[] args) {
/* YOUR CODE HERE */
}
}
Sorry I can't comment yet.
But yes, you cannot call non static method inside static method.
Static belongs to class and non-static belongs to the instance you can look more into that in google.
If SlopeCompare should be static you need to have an instance of Point to call slopeTo.
this in this.slopeTo() represents SlopeCompare instance, inner class can indeed access fields and methods of outer class, but it's not inherit, so you can not access slopeTo() with this keywords, you can ues outer.this to get an instance of the outer class.
Two solutions for references:
1.define slopeTo() method with static:
public static double slopeTo(Point that) {
2.remove the static keywords from the member class:
private class SlopeCompare implements Comparator<Point> {

How do I create a interactive canvas basic geometric shapes

I am currently on spring break and since I only work 25 hours a week I have too much free time on my hands. I am a Computer Science student and I decided to spend my free time improving my coding skills and my understanding of electromagnetic physics by creating a very simple calculator that is used to solve Coulomb's law with vectors which are used to solve the force between any two charged particles in a system of charged particles.
Now I have a somewhat accurate calculator working, I still have a few minor inaccuracies that I need to address but the code can be found down below, but it still works enough for the next step I would like to achieve.
This next step for me is to create a GUI and an interactive graph for the users to see. I say interactive because my ideal program would give the user the ability to drag and drop points on the canvas all the while the program is calculating the force vectors and net force that is present between the points the user places on the space. I would also be satisfied with just being able to draw the graph given the charges and XY-coordinates as well.
My question is does anyone know of any good tutorials or respectable libraries that I can look into to achieve either of these two ideas? I have a strong background in Java so I would prefer this to be done in Java, but I am never one to step away from learning a new language when I need too.
Code:
Charge.java
package objects;
/**
* Charge is an object used to represent an arbitrarily charged particle in some
* XY-plane. This class will store the value of the charge, the XY-coordinates
* of that charge's location, and functions to access these values.
*
* #author Seth
*
*/
public class Charge {
private double q; // the charge of the particle in Coulombs
private double x; // the location along the x-axis of the charge
private double y; // the location along the y-axis of the charge
public Charge(double x, double y, double q) {
this.x = x;
this.y = y;
this.q = q;
}
/**
* public method to get q
*
* #return
* double - value of the Charge object
*/
public double getQ() {
if (this != null)
return q;
else
return 0;
}
/**
* public method to get x
*
* #return
* double - value of the x coordinate
*/
public double getX() {
if (this != null)
return x;
else
return 0;
}
/**
* public method to get y
*
* #return
* double - value of the y coordinate
*/
public double getY() {
if (this != null)
return y;
else
return 0;
}
}
ElectricForceCalculator.java
package objects;
/**
* ElectricForceCalculator is a class that has the ability to solve the net
* force between two charged particles in a xy-plane
*
* #author Seth
*
*/
public class ElectricForceCalculator {
/**
* Private method used to find the force between two charges
*
* #param Q
* Charge - The charged we are focused on
* #param q
* Charge - The second charge effecting Q
* #return double array - the force vectors found where i = 0 is the x
* direction and i = 1 is the y direction
*/
private double[] calcForceHelper(Charge Q, Charge q) {
double radius, quanOfCharge;
double[] radiusVector = new double[2], forceVector = new double[2];
double x1 = Q.getX(), y1 = Q.getY();
double x2 = q.getX(), y2 = q.getY();
double q1 = Q.getQ(), q2 = q.getQ();
System.out.print("Calculating radius of Q and q...\n\t");
radius = calcRadius(x1, x2, y1, y2);
System.out.print("Calculating radiusVector of Q and q...\n\t");
radiusVector = calcRadiusVector(x1, x2, y1, y2, radius);
System.out.print("Calculating quantityOfCharge of Q and q...\n\t");
quanOfCharge = calcCharge(q1, q2, radius);
System.out.print("Calculating Force Vector of Q and q...\n\t");
forceVector = calcForceVector(radius, radiusVector, quanOfCharge);
return forceVector;
}
/**
* Public method used to find the overall net force of a system of charged
* particles
*
* #param Q
* Charge - the Charge object we are focused on
* #param q
* Charge array - the list of all the other Charge object
* effecting Q
* #param numCharges
* int - the number of indices found in the list of Charge
* objects q
* #return double - value of the net force experienced by Charge object Q
*/
public double calcForce(Charge Q, Charge[] q, int numCharges) {
double result;
double[] sum = { 0.0, 0.0 }, tempSum = new double[2];
for (int i = 0; i < numCharges - 1; i++) {
tempSum = calcForceHelper(Q, q[i]); // Help with readability to call
// method helper
fixSigns(Q, q[i], tempSum);
sum[0] += tempSum[0];
sum[1] += tempSum[1];
}
System.out.println("\nOverall force Vector on Q = (" + sum[0] + ")x + (" + sum[1] + ")y.");
result = Math.pow(sum[0], 2) + Math.pow(sum[1], 2);
result = Math.sqrt(result);
double theta = calcTheta(sum);
System.out.print("Force on charge Q by all other charges = " + result + " at ");
if (sum[1] > 0) {
if (sum[0] > 0)
System.out.print((float) Math.round(90 - theta) + " degrees.");
else
System.out.print((float) Math.round(180 - theta) + " degrees.");
} else {
if (sum[0] > 0)
System.out.print((float) Math.round(180 + theta) + " degrees.");
else
System.out.print((float) Math.round(270 + theta) + " degrees.");
}
return result;
}
/**
* Method used to assign negative values to any forces that should be
* negative
*
* #param Q
* Charge - the charge we are focused on
* #param q
* charge - the charge effecting Q
* #param tempSum
* the force vectors we are fixing, if needed
*/
private void fixSigns(Charge Q, Charge q, double[] tempSum) {
if (Q.getQ() < 0 && q.getQ() < 0) {
if (q.getX() > Q.getX())
tempSum[0] *= -1;
if (q.getY() > Q.getY())
tempSum[1] *= -1;
} else if (Q.getQ() > 0 && q.getQ() > 0) {
if (q.getX() > Q.getX())
tempSum[0] *= -1;
if (q.getY() > Q.getY())
tempSum[1] *= -1;
} else {
if (q.getX() < Q.getX())
tempSum[0] *= -1;
if (q.getY() < Q.getY())
tempSum[1] *= -1;
}
}
/**
* Private method used to calculate the angle Theta between two vectors
*
* #param forceVector
* double array - the force vectors we are finding the angle
* between
* #return double - the angle between the two force vectors given
*/
private double calcTheta(double[] vectors) {
double result = Math.abs(vectors[1]) / Math.abs(vectors[0]);// finds
// angle
// between 0
// and 90
result = Math.toDegrees(Math.atan(result));
return result;
}
/**
* Private method used to calculate the force vectors experienced by a
* charged particle
*
* #param radius
* double - distance between two charges
* #param radiusVector
* double array - the radius vectors between two charges
* #param quanOfCharge
* double - the quantity of charge given by k(coulomb's constant)
* * charge of Q * charge of q
* #return double array - the force vectors experienced by two charges
*/
private double[] calcForceVector(double radius, double[] radiusVector, double quanOfCharge) {
double[] result = new double[2];
double theta = calcTheta(radiusVector), magnitude = quanOfCharge;
result[0] = magnitude * Math.cos(Math.toRadians(theta));
result[1] = magnitude * Math.sin(Math.toRadians(theta));
System.out.print("Force Vector = (" + result[0] + ")x + (" + result[1] + ")y.\n");
return result;
}
/**
* private method used to calculate the quantity of charge between two
* charged particles(k * charge of Q * charge of q)
*
* #param Q
* double - the charge in Coulombs of the Charge object Q
* #param q
* double - the charge in Coulombs of the Charge object q
* #return double - the quantity of charge
*/
private double calcCharge(double Q, double q, double d) {
double result;
result = (((Q * q) / (d * d)) * 9E9);
result = Math.abs(result);
System.out.print("Quantity of charge(Q*q*k) = " + result + "\n");
return result;
}
/**
* Private method used to calculate the radius vector between two points on
* a xy-plane
*
* #param x1
* double - x coordinate of the Charge object Q
* #param x2
* double - y coordinate of the Charge object q
* #param y1
* double - x coordinate of the Charge object Q
* #param y2
* double - y coordinate of the Charge object q
* #param radius
* double - distance between the two points
* #return double array - the distance vectors between two charges
*/
private static double[] calcRadiusVector(double x1, double x2, double y1, double y2, double radius) {
double[] result = new double[2];
result[0] = (x2 - x1) / radius;
result[1] = (y2 - y1) / radius;
result[0] = Math.abs(result[0]);
result[1] = Math.abs(result[1]);
System.out.print("Radius vector = (" + result[0] + ")x + (" + result[1] + ")y\n");
return result;
}
/**
* Private method used to calculate the distance between two points on a
* xy-plane using the distance formula or [(x2-x1)+(y2-y1]^(1/2)
*
* #param x1
* double - x coordinate of the Charge object Q
* #param x2
* double - y coordinate of the Charge object q
* #param y1
* double - x coordinate of the Charge object Q
* #param y2
* double - y coordinate of the Charge object q
* #return double - distance between the two points given
*/
private double calcRadius(double x1, double x2, double y1, double y2) {
double distance = Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2);
distance = Math.sqrt(distance);
System.out.print("Radius = " + distance + "\n");
return distance;
}
/**
* Main
*
* #param args
*/
public static void main(String[] args) {
Charge Q = new Charge(-.02, .015, -4E-6);
Charge[] q = new Charge[2];
q[0] = new Charge(.035, .005, 3E-6);
q[1] = new Charge(-.0837, .0262, 4E-6);
ElectricForceCalculator calc = new ElectricForceCalculator();
calc.calcForce(Q, q, 3);
}
}
Sample output:
charge Q is -4.0E-6 C at (x,y) = (-0.02, 0.015).
charge q1 is 3.0E-6 C at (x,y) = (0.035, 0.005).
charge q1 is 4.0E-6 C at (x,y) = (-0.0837, 0.0262).
Calculating radius of Q and q...
Radius = 0.05590169943749475
Calculating radiusVector of Q and q...
Radius vector = (0.9838699100999075)x + (0.17888543819998312)y
Calculating quantityOfCharge of Q and q...
Quantity of charge(Q*q*k) = 34.559999999999995
Calculating Force Vector of Q and q...
Force Vector = (34.0025440930528)x + (6.182280744191415)y.
Calculating radius of Q and q...
Radius = 0.06467712114805357
Calculating radiusVector of Q and q...
Radius vector = (0.984892321570454)x + (0.17316788071568426)y
Calculating quantityOfCharge of Q and q...
Quantity of charge(Q*q*k) = 34.4239839545986
Calculating Force Vector of Q and q...
Force Vector = (33.903917474748674)x + (5.96112834720856)y.
Overall force Vector on Q = (0.09862661830412378)x + (-0.2211523969828546)y.
Force on charge Q by all other charges = 0.24214787327038295

Java - Exception in thread "main" java.lang.StackOverflowError when applying recursion

I wrote a program to calculate values for the Zeta function through the Abel-Plana formula.
Depending on the value of the error term referenced, Java returns an error message for Exception in thread "main" java.lang.StackOverflowError.
Here is a working copy of the program with test values. The Complex.Java program is a helper program.
/**************************************************************************
**
** Abel-Plana Formula for the Zeta Function
**
**************************************************************************
** Axion004
** 08/16/2015
**
** This program computes the value for Zeta(z) using a definite integral
** approximation through the Abel-Plana formula. The Abel-Plana formula
** can be shown to approximate the value for Zeta(s) through a definite
** integral. The integral approximation is handled through the Composite
** Simpson's Rule known as Adaptive Quadrature.
**************************************************************************/
import java.util.*;
import java.math.*;
public class AbelMain extends Complex {
public static void main(String[] args) {
AbelMain();
}
// Main method
public static void AbelMain() {
double re = 0, im = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.println("Calculation of the Riemann Zeta " +
"Function in the form Zeta(s) = a + ib.");
System.out.println();
System.out.print("Enter the value of [a] inside the Riemann Zeta " +
"Function: ");
try {
re = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for a.");
}
System.out.print("Enter the value of [b] inside the Riemann Zeta " +
"Function: ");
try {
im = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for b.");
}
start = System.currentTimeMillis();
Complex z = new Complex(re, im);
System.out.println("The value for Zeta(s) is " + AbelPlana(z));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> Numerator = Sin(z * arctan(t))
* <br> Denominator = (1 + t^2)^(z/2) * (e^(pi*t) + 1)
* #param t - the value of t passed into the integrand.
* #param z - The complex value of z = a + i*b
* #return the value of the complex function.
*/
public static Complex f(double t, Complex z) {
Complex num = (z.multiply(Math.atan(t))).sin();
Complex D1 = new Complex(1 + t*t, 0).pow(z.divide(2.0));
double D2 = Math.pow(Math.E, Math.PI * t) + 1.0;
Complex den = D1.multiply(D2);
return num.divide(den);
}
/**
* Adaptive quadrature - See http://www.mathworks.com/moler/quad.pdf
* #param a - the lower bound of integration.
* #param b - the upper bound of integration.
* #param z - The complex value of z = a + i*b
* #return the approximate numerical value of the integral.
*/
public static Complex adaptiveQuad(double a, double b, Complex z) {
BigDecimal EPSILON = new BigDecimal(1E-20);
double step = b - a;
double c = (a + b) / 2.0;
double d = (a + c) / 2.0;
double e = (b + c) / 2.0;
Complex S1 = (f(a, z).add(f(c, z).multiply(4)).add(f(b, z))).
multiply(step / 6.0);
Complex S2 = (f(a, z).add(f(d, z).multiply(4)).add(f(c, z).multiply(2))
.add(f(e, z).multiply(4)).add(f(b, z))).multiply(step / 12.0);
Complex result = (S2.minus(S1)).divide(15.0);
if(BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON) == -1
|| BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON)
== 0)
return S2.add(result);
else
return adaptiveQuad(a, c, z).add(adaptiveQuad(c, b, z));
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> C1 = 2^(z-1) / (z-1)
* <br> C2 = 2^(z)
* #param z - The complex value of z = a + i*b
* #return the value of Zeta(z) through C1, C2, and the
* quadrature approximation.
*/
public static Complex AbelPlana(Complex z) {
Complex two = new Complex(2.0, 0.0);
Complex C1 = two.pow(z.minus(1.0)).divide(z.minus(1.0));
Complex C2 = two.pow(z);
Complex mult = C2.multiply(adaptiveQuad(0, 10, z));
if ( z.re < 0 && z.re % 2 == 0 && z.im == 0)
return new Complex(0.0, 0.0);
else
return C1.minus(mult);
}
// Needed to reference the super class
public AbelMain(double re, double im) {
super(re, im);
}
}
The BigDecimal EPSILON = new BigDecimal(1E-20); variable works fine and returns values.
Calculation of the Riemann Zeta Function in the form Zeta(s) = a + ib.
Enter the value of [a] inside the Riemann Zeta Function: 54
Enter the value of [b] inside the Riemann Zeta Function: 2
The value for Zeta(s) is 3.742894786684807E13 + 1.6565035537902216E14*i
Total time taken is 0.01 seconds.
Helper program
/**************************************************************************
**
** Complex Numbers
**
**************************************************************************
** Axion004
** 08/20/2015
**
** This class is necessary as a helper class for the calculation of
** imaginary numbers. The calculation of Zeta(z) inside AbelMain is in
** the form of z = a + i*b.
**************************************************************************/
public class Complex extends Object{
public double re;
public double im;
/**
Constructor for the complex number z = a + i*b
#param re Real part
#param im Imaginary part
*/
public Complex (double re, double im) {
this.re = re;
this.im = im;
}
/**
Real part of the Complex number
#return Re[z] where z = a + i*b.
*/
public double real() {
return re;
}
/**
Imaginary part of the Complex number
#return Im[z] where z = a + i*b.
*/
public double imag() {
return im;
}
/**
Complex conjugate of the Complex number
in which the conjugate of z is z-bar.
#return z-bar where z = a + i*b and z-bar = a - i*b
*/
public Complex conjugate() {
return new Complex(re, -im);
}
/**
Addition of two Complex numbers (z is unchanged).
<br>(a+i*b) + (c+i*d) = (a+c) + i*(b+d)
#param t is the number to add.
#return z+t where z = a+i*b and t = c+i*d
*/
public Complex add(Complex t) {
return new Complex(re + t.real(), im + t.imag());
}
/**
Addition of Complex number and a double.
#param d is the number to add.
#return z+d where z = a+i*b and d = double
*/
public Complex add(double d){
return new Complex(this.re + d, this.im);
}
/**
Subtraction of two Complex numbers (z is unchanged).
<br>(a+i*b) - (c+i*d) = (a-c) + i*(b-d)
#param t is the number to subtract.
#return z-t where z = a+i*b and t = c+i*d
*/
public Complex minus(Complex t) {
return new Complex(re - t.real(), im - t.imag());
}
/**
Subtraction of Complex number and a double.
#param d is the number to subtract.
#return z-d where z = a+i*b and d = double
*/
public Complex minus(double d){
return new Complex(this.re - d, this.im);
}
/**
Complex multiplication (z is unchanged).
<br> (a+i*b) * (c+i*d) = (a*c)+ i(b*c) + i(a*d) - (b*d)
#param t is the number to multiply by.
#return z*t where z = a+i*b and t = c+i*d
*/
public Complex multiply(Complex t) {
return new Complex(re * t.real() - im * t.imag(), re *
t.imag() + im * t.real());
}
/**
Complex multiplication by a double.
#param d is the double to multiply by.
#return z*d where z = a+i*b and d = double
*/
public Complex multiply(double d){
return new Complex(this.re * d,this.im * d);}
/**
Modulus of a Complex number or the distance from the origin in
* the polar coordinate plane.
#return |z| where z = a + i*b.
*/
public double mod() {
if ( re != 0.0 || im != 0.0)
return Math.sqrt(re*re + im*im);
else
return 0.0;
}
/**
* Modulus of a Complex number squared
* #param z = a + i*b
* #return |z|^2 where z = a + i*b
*/
public double abs(Complex z) {
return Math.sqrt(Math.pow(re*re, 2) + Math.pow(im*im, 2));
}
/**
Division of Complex numbers (doesn't change this Complex number).
<br>(a+i*b) / (c+i*d) = (a+i*b)*(c-i*d) / (c+i*d)*(c-i*d) =
* (a*c+b*d) + i*(b*c-a*d) / (c^2-d^2)
#param t is the number to divide by
#return new Complex number z/t where z = a+i*b
*/
public Complex divide (Complex t) {
double denom = Math.pow(t.mod(), 2); // Square the modulus
return new Complex((re * t.real() + im * t.imag()) / denom,
(im * t.real() - re * t.imag()) / denom);
}
/**
Division of Complex number by a double.
#param d is the double to divide
#return new Complex number z/d where z = a+i*b
*/
public Complex divide(double d){
return new Complex(this.re / d, this.im / d);
}
/**
Exponential of a complex number (z is unchanged).
<br> e^(a+i*b) = e^a * e^(i*b) = e^a * (cos(b) + i*sin(b))
#return exp(z) where z = a+i*b
*/
public Complex exp () {
return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) *
Math.sin(im));
}
/**
The Argument of a Complex number or the angle in radians
with respect to polar coordinates.
<br> Tan(theta) = b / a, theta = Arctan(b / a)
<br> a is the real part on the horizontal axis
<br> b is the imaginary part of the vertical axis
#return arg(z) where z = a+i*b.
*/
public double arg() {
return Math.atan2(im, re);
}
/**
The log or principal branch of a Complex number (z is unchanged).
<br> Log(a+i*b) = ln|a+i*b| + i*Arg(z) = ln(sqrt(a^2+b^2))
* + i*Arg(z) = ln (mod(z)) + i*Arctan(b/a)
#return log(z) where z = a+i*b
*/
public Complex log() {
return new Complex(Math.log(this.mod()), this.arg());
}
/**
The square root of a Complex number (z is unchanged).
Returns the principal branch of the square root.
<br> z = e^(i*theta) = r*cos(theta) + i*r*sin(theta)
<br> r = sqrt(a^2+b^2)
<br> cos(theta) = a / r, sin(theta) = b / r
<br> By De Moivre's Theorem, sqrt(z) = sqrt(a+i*b) =
* e^(i*theta / 2) = r(cos(theta/2) + i*sin(theta/2))
#return sqrt(z) where z = a+i*b
*/
public Complex sqrt() {
double r = this.mod();
double halfTheta = this.arg() / 2;
return new Complex(Math.sqrt(r) * Math.cos(halfTheta), Math.sqrt(r) *
Math.sin(halfTheta));
}
/**
The real cosh function for Complex numbers.
<br> cosh(theta) = (e^(theta) + e^(-theta)) / 2
#return cosh(theta)
*/
private double cosh(double theta) {
return (Math.exp(theta) + Math.exp(-theta)) / 2;
}
/**
The real sinh function for Complex numbers.
<br> sinh(theta) = (e^(theta) - e^(-theta)) / 2
#return sinh(theta)
*/
private double sinh(double theta) {
return (Math.exp(theta) - Math.exp(-theta)) / 2;
}
/**
The sin function for the Complex number (z is unchanged).
<br> sin(a+i*b) = cosh(b)*sin(a) + i*(sinh(b)*cos(a))
#return sin(z) where z = a+i*b
*/
public Complex sin() {
return new Complex(cosh(im) * Math.sin(re), sinh(im)*
Math.cos(re));
}
/**
The cos function for the Complex number (z is unchanged).
<br> cos(a +i*b) = cosh(b)*cos(a) + i*(-sinh(b)*sin(a))
#return cos(z) where z = a+i*b
*/
public Complex cos() {
return new Complex(cosh(im) * Math.cos(re), -sinh(im) *
Math.sin(re));
}
/**
The hyperbolic sin of the Complex number (z is unchanged).
<br> sinh(a+i*b) = sinh(a)*cos(b) + i*(cosh(a)*sin(b))
#return sinh(z) where z = a+i*b
*/
public Complex sinh() {
return new Complex(sinh(re) * Math.cos(im), cosh(re) *
Math.sin(im));
}
/**
The hyperbolic cosine of the Complex number (z is unchanged).
<br> cosh(a+i*b) = cosh(a)*cos(b) + i*(sinh(a)*sin(b))
#return cosh(z) where z = a+i*b
*/
public Complex cosh() {
return new Complex(cosh(re) *Math.cos(im), sinh(re) *
Math.sin(im));
}
/**
The tan of the Complex number (z is unchanged).
<br> tan (a+i*b) = sin(a+i*b) / cos(a+i*b)
#return tan(z) where z = a+i*b
*/
public Complex tan() {
return (this.sin()).divide(this.cos());
}
/**
The arctan of the Complex number (z is unchanged).
<br> tan^(-1)(a+i*b) = 1/2 i*(log(1-i*(a+b*i))-log(1+i*(a+b*i))) =
<br> -1/2 i*(log(i*a - b+1)-log(-i*a + b+1))
#return arctan(z) where z = a+i*b
*/
public Complex atan(){
Complex ima = new Complex(0.0,-1.0); //multiply by negative i
Complex num = new Complex(this.re,this.im-1.0);
Complex den = new Complex(-this.re,-this.im-1.0);
Complex two = new Complex(2.0, 0.0); // divide by 2
return ima.multiply(num.divide(den).log()).divide(two);
}
/**
* The Math.pow equivalent of two Complex numbers.
* #param z - the complex base in the form z = a + i*b
* #return z^y where z = a + i*b and y = c + i*d
*/
public Complex pow(Complex z){
Complex a = z.multiply(this.log());
return a.exp();
}
/**
* The Math.pow equivalent of a Complex number to the power
* of a double.
* #param d - the double to be taken as the power.
* #return z^d where z = a + i*b and d = double
*/
public Complex pow(double d){
Complex a=(this.log()).multiply(d);
return a.exp();
}
/**
Override the .toString() method to generate complex numbers, the
* string representation is now a literal Complex number.
#return a+i*b, a-i*b, a, or i*b as desired.
*/
public String toString() {
if (re != 0.0 && im > 0.0) {
return re + " + " + im +"*i";
}
if (re !=0.0 && im < 0.0) {
return re + " - "+ (-im) + "*i";
}
if (im == 0.0) {
return String.valueOf(re);
}
if (re == 0.0) {
return im + "*i";
}
return re + " + i*" + im;
}
}
Increasing the error term to BigDecimal EPSILON = new BigDecimal(1E-50); causes the program to return java.lang.StackOverflowError.
/**************************************************************************
**
** Abel-Plana Formula for the Zeta Function
**
**************************************************************************
** Axion004
** 08/16/2015
**
** This program computes the value for Zeta(z) using a definite integral
** approximation through the Abel-Plana formula. The Abel-Plana formula
** can be shown to approximate the value for Zeta(s) through a definite
** integral. The integral approximation is handled through the Composite
** Simpson's Rule known as Adaptive Quadrature.
**************************************************************************/
import java.util.*;
import java.math.*;
public class AbelMain extends Complex {
public static void main(String[] args) {
AbelMain();
}
// Main method
public static void AbelMain() {
double re = 0, im = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.println("Calculation of the Riemann Zeta " +
"Function in the form Zeta(s) = a + ib.");
System.out.println();
System.out.print("Enter the value of [a] inside the Riemann Zeta " +
"Function: ");
try {
re = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for a.");
}
System.out.print("Enter the value of [b] inside the Riemann Zeta " +
"Function: ");
try {
im = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for b.");
}
start = System.currentTimeMillis();
Complex z = new Complex(re, im);
System.out.println("The value for Zeta(s) is " + AbelPlana(z));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> Numerator = Sin(z * arctan(t))
* <br> Denominator = (1 + t^2)^(z/2) * (e^(pi*t) + 1)
* #param t - the value of t passed into the integrand.
* #param z - The complex value of z = a + i*b
* #return the value of the complex function.
*/
public static Complex f(double t, Complex z) {
Complex num = (z.multiply(Math.atan(t))).sin();
Complex D1 = new Complex(1 + t*t, 0).pow(z.divide(2.0));
double D2 = Math.pow(Math.E, Math.PI * t) + 1.0;
Complex den = D1.multiply(D2);
return num.divide(den);
}
/**
* Adaptive quadrature - See http://www.mathworks.com/moler/quad.pdf
* #param a - the lower bound of integration.
* #param b - the upper bound of integration.
* #param z - The complex value of z = a + i*b
* #return the approximate numerical value of the integral.
*/
public static Complex adaptiveQuad(double a, double b, Complex z) {
BigDecimal EPSILON = new BigDecimal(1E-50);
double step = b - a;
double c = (a + b) / 2.0;
double d = (a + c) / 2.0;
double e = (b + c) / 2.0;
Complex S1 = (f(a, z).add(f(c, z).multiply(4)).add(f(b, z))).
multiply(step / 6.0);
Complex S2 = (f(a, z).add(f(d, z).multiply(4)).add(f(c, z).multiply(2))
.add(f(e, z).multiply(4)).add(f(b, z))).multiply(step / 12.0);
Complex result = (S2.minus(S1)).divide(15.0);
if(BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON) == -1
|| BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON)
== 0)
return S2.add(result);
else
return adaptiveQuad(a, c, z).add(adaptiveQuad(c, b, z));
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> C1 = 2^(z-1) / (z-1)
* <br> C2 = 2^(z)
* #param z - The complex value of z = a + i*b
* #return the value of Zeta(z) through C1, C2, and the
* quadrature approximation.
*/
public static Complex AbelPlana(Complex z) {
Complex two = new Complex(2.0, 0.0);
Complex C1 = two.pow(z.minus(1.0)).divide(z.minus(1.0));
Complex C2 = two.pow(z);
Complex mult = C2.multiply(adaptiveQuad(0, 10, z));
if ( z.re < 0 && z.re % 2 == 0 && z.im == 0)
return new Complex(0.0, 0.0);
else
return C1.minus(mult);
}
// Needed to reference the super class
public AbelMain(double re, double im) {
super(re, im);
}
}
Test Run
Calculation of the Riemann Zeta Function in the form Zeta(s) = a + ib.
Enter the value of [a] inside the Riemann Zeta Function: 54
Enter the value of [b] inside the Riemann Zeta Function: 2
Exception in thread "main" java.lang.StackOverflowError
at sun.misc.FpUtils.getExponent(FpUtils.java:147)
at java.lang.Math.getExponent(Math.java:1310)
at java.lang.StrictMath.floorOrCeil(StrictMath.java:355)
at java.lang.StrictMath.floor(StrictMath.java:340)
at java.lang.Math.floor(Math.java:424)
at sun.misc.FloatingDecimal.dtoa(FloatingDecimal.java:620)
at sun.misc.FloatingDecimal.<init>(FloatingDecimal.java:459)
at java.lang.Double.toString(Double.java:196)
at java.math.BigDecimal.valueOf(BigDecimal.java:1069)
at AbelMain.adaptiveQuad(AbelMain.java:92)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
These two lines point to
if(BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON) == -1
|| BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON)
== 0)
and
return adaptiveQuad(a, c, z).add(adaptiveQuad(c, b, z));
Is this error due to infinite recursion? That value for epsilon might have to be above a certain threshold?
Yes, StackOverflowError is most due to infinite recursion.
You could try debugging the code, but in instances like this, it's probably easier for the old method: Insert a print statement in the beginning of the adaptiveQuad method, printing the current state/parameters.
When it dies, a clear pattern may be visible.
You mix "float" and "BigDecimal", with terrific side effects... in particular (I tried with input data 54 and 2), when you use "step" float variable, as result of difference between a an b, after a while it reaches a "fixed point" of 1.0587911840678754E-22, due to the internal representation of Complex data, where you use floats.
Well, at this point, this "step" never change, S1 and S2 neither, and difference remains the same ("result" evaluates 0.0, -2.3915493791143544E-44) so it never goes under EPSILON (as 1E-50) and algorithm recurses infinitely (or better, until explodes). In other words, you avoided approximations from a side, using BigDecimal, but you reintroduced it via float usage :)
Try to remove float usage everywhere (in Complex too), and everything should run fine.

Categories

Resources