-
Notifications
You must be signed in to change notification settings - Fork 19.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Complex Numbers Utils #5128
Closed
Closed
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
106bd45
Update directory
rozi26 191697c
Update directory
rozi26 de68d67
add basic complex numbers methods and unit tests
rozi26 fcfeea7
add trigs
rozi26 175e125
add links to sources
rozi26 6ce45ca
add exceptions for the trigonometric functions
rozi26 61b3cc5
format the code using clang
rozi26 f6fe7c2
add unit tests
rozi26 0f6c801
Merge branch 'master' of https://github.com/rozi26/java_algo_fork1
rozi26 2764454
run clang format on the test file
rozi26 8ecf1ff
Merge branch 'master' into feature/improve_code_look
rozi26 b813d2d
Merge branch 'feature/improve_code_look' of https://github.com/rozi26…
rozi26 b30eaab
temp changes
rozi26 0bf5319
make the code ready for pull request
rozi26 799ba61
make the code ready for pull request
rozi26 d5d6ee0
change the order or final static
rozi26 3495410
Update src/test/java/com/thealgorithms/maths/ComplexNumberUtilTest.java
rozi26 95cae76
Update src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
rozi26 592f443
Update src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
rozi26 6f12753
Update src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
rozi26 428b97d
Merge branch 'master' into feature/improve_code_look
rozi26 d629eec
Update directory
rozi26 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
264 changes: 264 additions & 0 deletions
264
src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,264 @@ | ||
package com.thealgorithms.maths; | ||
|
||
public class ComplexNumberUtil { | ||
|
||
public static class ComplexNumber { | ||
public final double REAL; | ||
public final double IMAGINARY; | ||
|
||
public ComplexNumber(double real, double imaginary) { | ||
REAL = real; | ||
IMAGINARY = imaginary; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (obj instanceof ComplexNumber num) { | ||
return this.REAL == num.REAL && this.IMAGINARY == num.IMAGINARY; | ||
} | ||
|
||
return super.equals(obj); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return REAL + ((IMAGINARY < 0) ? (" - " + Math.abs(IMAGINARY)) : (" + " + IMAGINARY)) + "i"; | ||
} | ||
} | ||
|
||
public static final ComplexNumber ZERO = new ComplexNumber(0, 0); | ||
public static final ComplexNumber ONE = new ComplexNumber(1, 0); | ||
public static final ComplexNumber TWO = new ComplexNumber(2, 0); | ||
public static final ComplexNumber PLUS_I = new ComplexNumber(0, 1); | ||
public static final ComplexNumber MINUS_I = new ComplexNumber(0, -1); | ||
|
||
/** | ||
* add two complex numbers | ||
* @param num1 the first complex number | ||
* @param num2 the second complex number | ||
* @return the sum of num1 and num2 | ||
*/ | ||
public static ComplexNumber add(ComplexNumber num1, ComplexNumber num2) { | ||
return new ComplexNumber(num1.REAL + num2.REAL, num1.IMAGINARY + num2.IMAGINARY); | ||
} | ||
|
||
/** | ||
* Subtracts the second complex number from the first complex number. | ||
* | ||
* @param num1 the first complex number | ||
* @param num2 the second complex number | ||
* @return the result of subtracting num2 from num1 | ||
*/ | ||
public static ComplexNumber subtract(ComplexNumber num1, ComplexNumber num2) { | ||
return new ComplexNumber(num1.REAL - num2.REAL, num1.IMAGINARY - num2.IMAGINARY); | ||
} | ||
|
||
/** | ||
* Multiplies two complex numbers. | ||
* | ||
* @param num1 the first complex number | ||
* @param num2 the second complex number | ||
* @return the product of num1 and num2 | ||
* @link <a href="https://en.wikipedia.org/wiki/Complex_number#Multiplication">...</a> | ||
*/ | ||
public static ComplexNumber multiply(ComplexNumber num1, ComplexNumber num2) { | ||
return new ComplexNumber(num1.REAL * num2.REAL - num1.IMAGINARY * num2.IMAGINARY, num1.REAL * num2.IMAGINARY + num1.IMAGINARY * num2.REAL); | ||
} | ||
|
||
/** | ||
* Divides the first complex number by the second complex number. | ||
* | ||
* @param num1 the numerator complex number | ||
* @param num2 the denominator complex number | ||
* @return the result of dividing num1 by num2 | ||
* @throws RuntimeException if the divisor (num2) is zero | ||
* @link <a href="https://en.wikipedia.org/wiki/Complex_number#Complex_conjugate,_absolute_value_and_argument">...</a> | ||
*/ | ||
public static ComplexNumber divide(ComplexNumber num1, ComplexNumber num2) { | ||
final double divisor = num2.REAL * num2.REAL + num2.IMAGINARY * num2.IMAGINARY; | ||
if (divisor == 0) { | ||
throw new RuntimeException("Cannot divide by zero"); | ||
} | ||
|
||
return new ComplexNumber((num1.REAL * num2.REAL + num1.IMAGINARY * num2.IMAGINARY) / divisor, (num1.IMAGINARY * num2.REAL - num1.REAL * num2.IMAGINARY) / divisor); | ||
} | ||
|
||
/** | ||
* Computes the absolute value (magnitude) of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the absolute value of num | ||
* @link <a href="https://en.wikipedia.org/wiki/Complex_number#Complex_conjugate,_absolute_value_and_argument">...</a> | ||
*/ | ||
public static double abs(ComplexNumber num) { | ||
return Math.sqrt(num.REAL * num.REAL + num.IMAGINARY * num.IMAGINARY); | ||
} | ||
|
||
/** | ||
* Computes the exponential function of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return e raised to the power of num | ||
* @link <a href="https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex">...</a> | ||
*/ | ||
public static ComplexNumber exp(ComplexNumber num) { | ||
final double coefficient = Math.exp(num.REAL); | ||
return new ComplexNumber(coefficient * Math.cos(num.IMAGINARY), coefficient * Math.sin(num.IMAGINARY)); | ||
} | ||
|
||
/** | ||
* Computes the natural logarithm of a complex number. | ||
rozi26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* @param num the complex number | ||
* @return the natural logarithm of num | ||
* @throws RuntimeException if num is zero | ||
* @link <a href="https://en.wikipedia.org/wiki/Complex_logarithm#Calculating_the_principal_value">...</a> | ||
*/ | ||
public static ComplexNumber ln(ComplexNumber num) { | ||
rozi26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (num.equals(ZERO)) { | ||
throw new RuntimeException("Cannot take the logarithm of zero"); | ||
} | ||
|
||
return new ComplexNumber(Math.log(abs(num)), Math.atan2(num.IMAGINARY, num.REAL)); | ||
} | ||
|
||
/** | ||
* Computes the power of a complex number raised to another complex number. | ||
* | ||
* @param num1 the base complex number | ||
* @param num2 the exponent complex number | ||
* @return num1 raised to the power of num2 | ||
* link <a href="https://en.wikipedia.org/wiki/Exponentiation#Complex_exponents_with_a_positive_real_base">...</a> | ||
*/ | ||
public static ComplexNumber pow(ComplexNumber num1, ComplexNumber num2) { | ||
if (num1.equals(ZERO)) { | ||
return num2.equals(ZERO) ? ONE : ZERO; | ||
} | ||
|
||
return exp(multiply(ln(num1), num2)); | ||
} | ||
|
||
/** | ||
* Computes the square root of a complex number. | ||
rozi26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* @param num the complex number | ||
* @return the square root of num | ||
*/ | ||
public static ComplexNumber sqrt(ComplexNumber num) { | ||
return pow(num, new ComplexNumber(0.5, 0)); | ||
} | ||
|
||
/** | ||
* Computes the sine of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the sine of num | ||
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Relationship_to_exponential_function_">...</a>(Euler's_formula) | ||
*/ | ||
public static ComplexNumber sin(ComplexNumber num) { | ||
ComplexNumber exp1 = exp(multiply(num, PLUS_I)); | ||
ComplexNumber exp2 = exp(multiply(num, MINUS_I)); | ||
return divide(subtract(exp1, exp2), multiply(new ComplexNumber(2, 0), PLUS_I)); | ||
} | ||
|
||
/** | ||
* Computes the cosine of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the cosine of num | ||
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Relationship_to_exponential_function_">...</a>(Euler's_formula) | ||
*/ | ||
public static ComplexNumber cos(ComplexNumber num) { | ||
ComplexNumber exp1 = exp(multiply(num, PLUS_I)); | ||
ComplexNumber exp2 = exp(multiply(num, MINUS_I)); | ||
return divide(add(exp1, exp2), TWO); | ||
} | ||
|
||
/** | ||
* Computes the tangent of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the tangent of num | ||
* @throws RuntimeException if <code>num.real = pi*(n+0.5)</code> | ||
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions">...</a> | ||
*/ | ||
public static ComplexNumber tan(ComplexNumber num) { | ||
if (num.REAL % Math.PI == Math.PI / 2) { | ||
throw new RuntimeException("Cannot take the tan of a number where the real part can be expressed as pi*(n+0.5)"); | ||
} | ||
|
||
return divide(sin(num), cos(num)); | ||
} | ||
|
||
/** | ||
* Computes the cotangent of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the cotangent of num | ||
* @throws RuntimeException if <code>num.real = pi*n</code> | ||
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions">...</a> | ||
*/ | ||
public static ComplexNumber cot(ComplexNumber num) { | ||
if (num.REAL % Math.PI == 0) { | ||
throw new RuntimeException("Cannot take the cot of number with real part dividable by pi"); | ||
} | ||
|
||
return divide(cos(num), sin(num)); | ||
} | ||
|
||
/** | ||
* Computes the arcsine of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the arcsine of num | ||
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a> | ||
*/ | ||
public static ComplexNumber arcsin(ComplexNumber num) { | ||
ComplexNumber temp = sqrt(subtract(ONE, multiply(num, num))); | ||
return multiply(MINUS_I, ln(add(multiply(PLUS_I, num), temp))); | ||
} | ||
|
||
/** | ||
* Computes the arccosine of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the arccosine of num | ||
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a> | ||
*/ | ||
public static ComplexNumber arccos(ComplexNumber num) { | ||
ComplexNumber temp = sqrt(subtract(ONE, multiply(num, num))); | ||
return multiply(MINUS_I, ln(add(num, multiply(temp, PLUS_I)))); | ||
} | ||
|
||
/** | ||
* Computes the arctangent of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the arctangent of num | ||
* @throws RuntimeException if <code>num=i</code> or <code>num=-i</code> | ||
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a> | ||
*/ | ||
public static ComplexNumber arctan(ComplexNumber num) { | ||
if (num.equals(PLUS_I) || num.equals(MINUS_I)) { | ||
throw new RuntimeException("Cannot take the arctan of " + num); | ||
} | ||
|
||
return multiply(divide(MINUS_I, TWO), ln(divide(subtract(PLUS_I, num), add(PLUS_I, num)))); | ||
} | ||
|
||
/** | ||
* Computes the arccotangent of a complex number. | ||
* | ||
* @param num the complex number | ||
* @return the arccotangent of num | ||
* @throws RuntimeException if <code>num=i</code> or <code>num=-i</code> | ||
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a> | ||
*/ | ||
public static ComplexNumber arccot(ComplexNumber num) { | ||
if (num.equals(PLUS_I) || num.equals(MINUS_I)) { | ||
throw new RuntimeException("Cannot take the arccot of " + num); | ||
} | ||
|
||
return multiply(divide(MINUS_I, TWO), ln(divide(add(num, PLUS_I), subtract(num, PLUS_I)))); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you decide to make it a
static
method? In the standard implementation ofComplex
add
is an object method.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to make it a static method for a few reasons:
Uniformity in Code: The file MatrixUtil.java, which is similar to this, uses static methods for the operations.
Ease of Expansion: Creating independent static methods makes it easier to add more advanced operations for complex numbers than integrating additional code into the ComplexNumber class itself.
Clarity: I find it easier to conceptualize operations as direct interactions between two entities, A and B (i.e., how do you add them), rather than how one adds B to A.
These are my reasons, but if you believe it should be an instance method, I would be happy to make that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making them
static
you loose all of the object oriented magic. The whole thing could be then simpler, because theComplexNumberUtil
would not be needed. Furthermore, you have marked both of the fieldsREAL
andIMAGINARY
asfinal
, so it is pretty clear that theadd
method will not change them.