Repository: commons-numbers Updated Branches: refs/heads/master d22b6d863 -> fcccb0ecf
NUMBERS-68: Implement "parse" as the inverse function of "toString". The string representation handled by both methods is fixed (as is the case for the JDK number classes). Project: http://git-wip-us.apache.org/repos/asf/commons-numbers/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-numbers/commit/03384e60 Tree: http://git-wip-us.apache.org/repos/asf/commons-numbers/tree/03384e60 Diff: http://git-wip-us.apache.org/repos/asf/commons-numbers/diff/03384e60 Branch: refs/heads/master Commit: 03384e60dab8c6ac9a44c5bd9e9397b342b140fb Parents: d22b6d8 Author: Gilles Sadowski <gil...@harfang.homelinux.org> Authored: Wed Apr 25 11:41:04 2018 +0200 Committer: Gilles Sadowski <gil...@harfang.homelinux.org> Committed: Wed Apr 25 11:41:04 2018 +0200 ---------------------------------------------------------------------- .../apache/commons/numbers/complex/Complex.java | 63 +++++++++++--------- .../commons/numbers/complex/ComplexTest.java | 53 ++++++++++++++++ 2 files changed, 87 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/03384e60/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java ---------------------------------------------------------------------- diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java index 217c109..2cd2e0f 100644 --- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java +++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java @@ -20,8 +20,8 @@ package org.apache.commons.numbers.complex; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.lang.NumberFormatException; import org.apache.commons.numbers.core.Precision; + /** * Representation of a Complex number, i.e. a number which has both a * real and imaginary part. @@ -133,37 +133,33 @@ public final class Complex implements Serializable { } /** - * Parses a text expression in a String object to produce - * a Cartesian complex number. Acceptable formats are: - * <p><ul> * <li>Single number (parsed as real). Example: "3.14" - * <li>Single number with appended "i" (parsed as imaginary): "1.42i" - * <li>Pair of numbers, separated by plus sign and with appended i: "3 + 4i" - * </ul> - * @throws{ParseException, NumberFormatException} + * Parses a string that would be produced by {@link #toString()} + * and instantiates the corresponding object. + * + * @param s String representation. + * @return an instance. + * @throws IllegalArgumentException if the string does not + * conform to the specification. */ public static Complex parse(String s) { - final String[] terms = s.split("+"); - if (terms.length == 2) { - if (terms[1].indexOf("i") == terms[1].length()) { - String imagTerm = (String) terms[1].subSequence(0, terms[1].length()-1); - final double real = Double.parseDouble(terms[0]); - final double imaginary = Double.parseDouble(imagTerm); - return Complex.ofCartesian(real, imaginary); - } else { - throw new NumberFormatException("Expression must end with unique \"i\""); - } - } else if (terms.length == 1){ - if (terms[0].indexOf("i") == terms[0].length()) { - String imagTerm = (String) terms[0].subSequence(0, terms[0].length()-1); - final double imaginary = Double.parseDouble(imagTerm); - return Complex.ofCartesian(0, imaginary); - } else { - final double real = Double.parseDouble(terms[0]); - return Complex.ofReal(real); - } - } else { - throw new NumberFormatException("Invalid expression for Complex. See documentation for further information."); + final int len = s.length(); + final int startParen = s.indexOf("("); + if (startParen != 0) { + throw new ComplexParsingException("Missing start parenthesis"); + } + final int endParen = s.indexOf(")"); + if (endParen != len - 1) { + throw new ComplexParsingException("Missing end parenthesis"); } + final int comma = s.indexOf(","); + if (comma == -1) { + throw new ComplexParsingException("Missing comma"); + } + + final double re = Double.parseDouble(s.substring(startParen + 1, comma)); + final double im = Double.parseDouble(s.substring(comma + 1, endParen)); + + return ofCartesian(re, im); } /** @@ -1362,4 +1358,13 @@ public final class Complex implements Serializable { d != 0; } + /** See {@link #parse(String)}. */ + private static class ComplexParsingException extends IllegalArgumentException { + /** + * @param msg Error message. + */ + ComplexParsingException(String msg) { + super(msg); + } + } } http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/03384e60/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java ---------------------------------------------------------------------- diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java index 8247459..ad73c14 100644 --- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java +++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java @@ -836,4 +836,57 @@ public class ComplexTest { Assert.assertTrue(Double.isNaN(zeroNaN.getArgument())); Assert.assertTrue(Double.isNaN(NAN.getArgument())); } + + @Test + public void testParse() { + Assert.assertTrue(Complex.ZERO.equals(Complex.parse(Complex.ZERO.toString()))); + Assert.assertTrue(Complex.ONE.equals(Complex.parse(Complex.ONE.toString()))); + Assert.assertTrue(Complex.I.equals(Complex.parse(Complex.I.toString()))); + Assert.assertTrue(Complex.INF.equals(Complex.parse(Complex.INF.toString()))); + Assert.assertTrue(NAN.equals(Complex.parse(NAN.toString()))); + Assert.assertTrue(oneInf.equals(Complex.parse(oneInf.toString()))); + Assert.assertTrue(negInfZero.equals(Complex.parse(negInfZero.toString()))); + Assert.assertTrue(Complex.ofReal(pi).equals(Complex.parse(Complex.ofReal(pi).toString()))); + Assert.assertTrue(Complex.ofPolar(2, pi).equals(Complex.parse(Complex.ofPolar(2, pi).toString()))); + Assert.assertTrue(Complex.ofCis(pi).equals(Complex.parse(Complex.ofCis(pi).toString()))); + } + + @Test(expected=IllegalArgumentException.class) + public void testParseWrongStart() { + final String re = "1.234"; + final String im = "5.678"; + Complex.parse(re + "," + im + ")"); + } + @Test(expected=IllegalArgumentException.class) + public void testParseWrongEnd() { + final String re = "1.234"; + final String im = "5.678"; + Complex.parse("(" + re + "," + im); + } + @Test(expected=IllegalArgumentException.class) + public void testParseMissingSeparator() { + final String re = "1.234"; + final String im = "5.678"; + Complex.parse("(" + re + " " + im + ")"); + } + @Test(expected=IllegalArgumentException.class) + public void testParseInvalidRe() { + final String re = "I.234"; + final String im = "5.678"; + Complex.parse("(" + re + "," + im + ")"); + } + @Test(expected=IllegalArgumentException.class) + public void testParseInvalidIm() { + final String re = "1.234"; + final String im = "5.G78"; + Complex.parse("(" + re + "," + im + ")"); + } + + @Test + public void testParseSpaceAllowedAroundNumbers() { + final double re = 1.234; + final double im = 5.678; + final String str = "( " + re + " , " + im + " )"; + Assert.assertTrue(Complex.ofCartesian(re, im).equals(Complex.parse(str))); + } }