diff --git a/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/complexnumbers/ComplexNumber.java b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/complexnumbers/ComplexNumber.java new file mode 100644 index 0000000000..8e509cfbbb --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/complexnumbers/ComplexNumber.java @@ -0,0 +1,57 @@ +package com.baeldung.complexnumbers; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public record ComplexNumber(double real, double imaginary) { + + public static ComplexNumber fromString(String complexNumberStr) { + + Pattern pattern = Pattern.compile("(-?\\d*\\.?\\d+)?(?:([+-]?\\d*\\.?\\d+)i)?"); + Matcher matcher = pattern.matcher(complexNumberStr.replaceAll("\\s", "")); + + if (matcher.matches()) { + // Extract real and imaginary parts + String realPartStr = matcher.group(1); + String imaginaryPartStr = matcher.group(2); + + // Parse real part (if present) + double real = (realPartStr != null) ? Double.parseDouble(realPartStr) : 0; + + // Parse imaginary part (if present) + double imaginary = (imaginaryPartStr != null) ? Double.parseDouble(imaginaryPartStr) : 0; + return new ComplexNumber(real, imaginary); + } else { + throw new IllegalArgumentException("Invalid complex number format(" + complexNumberStr + "), supported format is `a+bi`"); + } + } + + public String toString() { + return real + "+" + imaginary + "i"; + } + + public ComplexNumber add(ComplexNumber that) { + return new ComplexNumber(real + that.real, imaginary + that.imaginary); + } + + public ComplexNumber multiply(ComplexNumber that) { + double newReal = this.real * that.real - this.imaginary * that.imaginary; + double newImaginary = this.real * that.imaginary + this.imaginary * that.real; + return new ComplexNumber(newReal, newImaginary); + } + + public ComplexNumber subtract(ComplexNumber that) { + return new ComplexNumber(real - that.real, imaginary - that.imaginary); + } + + public ComplexNumber divide(ComplexNumber that) { + if(that.real == 0 && that.imaginary == 0 ){ + throw new ArithmeticException("Division by 0 is not allowed!"); + } + double c2d2 = Math.pow(that.real, 2) + Math.pow(that.imaginary, 2); + double newReal = (this.real * that.real + this.imaginary * that.imaginary) / c2d2; + double newImaginary = (this.imaginary * that.real - this.real * that.imaginary) / c2d2; + return new ComplexNumber(newReal, newImaginary); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/complexnumbers/ComplexNumberOperationsUnitTest.java b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/complexnumbers/ComplexNumberOperationsUnitTest.java new file mode 100644 index 0000000000..b2b7253fb8 --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/complexnumbers/ComplexNumberOperationsUnitTest.java @@ -0,0 +1,103 @@ +package com.baeldung.complexnumbers; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class ComplexNumberOperationsUnitTest { + + @ParameterizedTest(name = "Multiplying {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, -11+23i", + "2, 4, 8", + "2, 4i, 8i", + "1+1i, 1+1i, 0+2i", + " 3+2i, 1 + 7i, -11 + 23i ", + "0+5i, 3+0i, 0+15i", + "0+0i, -2+0i, 0+0i", + "-3+2i, 1-7i, 11+23i", + "2+4i, 0, 0" + }) + public void givenTwoComplexNumbers_multiplyAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber product = complex1.multiply(complex2); + Assertions.assertTrue(isSame(product, expected)); + } + + @ParameterizedTest(name = "Adding {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, 4+9i", + "2, 4, 6", + "2, 4i, 2+4i", + "1+1i, 1+1i, 2+2i", + " 3+2i, 1 + 7i, 4 + 9i ", + "0+5i, 3+0i, 3+5i", + "0+0i, -2+0i, -2+0i", + "-3+2i, 1-7i, -2-5i", + "2+4i, 0, 2+4i" + }) + public void givenTwoComplexNumbers_addThemAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber sum = complex1.add(complex2); + Assertions.assertTrue(isSame(sum, expected)); + } + + @ParameterizedTest(name = "Subtracting {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, 2-5i", + "2, 4, -2", + "2, 4i, 2-4i", + "1+1i, 1+1i, 0", + " 3+ 2i, 1+ 7i, 2-5i", + "0+5i, 3+0i, -3+5i", + "0+0i, -2+0i, 2+0i", + "-3+2i, 1-7i, -4+9i", + "2+4i, 0, 2+4i" + }) + public void givenTwoComplexNumbers_subtractAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber sum = complex1.subtract(complex2); + Assertions.assertTrue(isSame(sum, expected)); + } + + @ParameterizedTest(name = "Dividing {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, 0.34-0.38i", + "2, 4, 0.5", + "2, 4i, 0-0.5i", + "1+1i, 1+1i, 1", + "3 + 2i, 1 + 7i, 0.34-0.38i", + "0+5i, 3+0i, 0+1.6666666666666667i", + "0+0i, -2+0i, 0+0i", + "-3+2i, 1-7i, -0.34-0.38i", + "2+4i, 1, 2+4i" + }) + public void givenTwoComplexNumbers_divideThemAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber sum = complex1.divide(complex2); + Assertions.assertTrue(isSame(sum, expected)); + } + + @Test + public void givenAComplexNumberAsZero_handleDivideByZeroScenario() { + ComplexNumber complex1 = new ComplexNumber(1, 1); + ComplexNumber zero = new ComplexNumber(0, 0); + Exception exception = Assertions.assertThrows(ArithmeticException.class, () -> { + complex1.divide(zero); + }); + Assertions.assertEquals(exception.getMessage(), "Division by 0 is not allowed!"); + } + + public boolean isSame(ComplexNumber result, ComplexNumber expected) { + return result.real() == expected.real() && result.imaginary() == expected.imaginary(); + } +}