[ 
https://issues.apache.org/jira/browse/MATH-1681?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18004843#comment-18004843
 ] 

Ruiqi Dong edited comment on MATH-1681 at 7/12/25 10:14 AM:
------------------------------------------------------------

Thank you for the feedback. Here's the fix for the current version:

1. In {{parse(String source)}} method, check for null result:
{code:java}
public Complex parse(String source) throws MathParseException {
    ParsePosition parsePosition = new ParsePosition(0);
    Complex result = parse(source, parsePosition);
    
    if (result == null) {
        throw new MathParseException(source,
                                     parsePosition.getErrorIndex(),
                                     Complex.class);
    }
    
    return result;
} {code}
2. Optionally, ensure position is reset in {{parse(String, ParsePosition)}} 
when imaginary character parsing fails:
{code:java}
// parse imaginary character
if (!CompositeFormat.parseFixedstring(source, getImaginaryCharacter(), pos)) {
    pos.setIndex(initialIndex);  // Add this line for consistency
    return null;
} {code}
This ensures the API contract is honored while the class remains in the library.


was (Author: JIRAUSER310071):
Thank you for the feedback. I understand ComplexFormat may be removed in the 
future. Here's the fix for the current version:

1. In {{parse(String source)}} method, check for null result:
{code:java}
public Complex parse(String source) throws MathParseException {
    ParsePosition parsePosition = new ParsePosition(0);
    Complex result = parse(source, parsePosition);
    
    if (result == null) {
        throw new MathParseException(source,
                                     parsePosition.getErrorIndex(),
                                     Complex.class);
    }
    
    return result;
} {code}
2. Optionally, ensure position is reset in {{parse(String, ParsePosition)}} 
when imaginary character parsing fails:
{code:java}
// parse imaginary character
if (!CompositeFormat.parseFixedstring(source, getImaginaryCharacter(), pos)) {
    pos.setIndex(initialIndex);  // Add this line for consistency
    return null;
} {code}
This ensures the API contract is honored while the class remains in the library.

> ComplexFormat.parse(String) returns null instead of throwing 
> MathParseException for invalid complex number strings
> ------------------------------------------------------------------------------------------------------------------
>
>                 Key: MATH-1681
>                 URL: https://issues.apache.org/jira/browse/MATH-1681
>             Project: Commons Math
>          Issue Type: Bug
>          Components: legacy
>    Affects Versions: 4.0-beta1
>            Reporter: Ruiqi Dong
>            Priority: Major
>   Original Estimate: 0.5h
>  Remaining Estimate: 0.5h
>
> The {{ComplexFormat.parse(String source)}} method violates its documented 
> contract by returning {{null}} instead of throwing {{MathParseException}} for 
> certain malformed complex number strings. According to the JavaDoc, the 
> method should "throw MathParseException if the beginning of the specified 
> string cannot be parsed," but it fails to do so in several cases.
>  
> *Test Case to Demonstrate the Bug:*
> {code:java}
> @Test
> public void 
> testParseShouldThrowExceptionForInvalidComplexMissingImaginaryCharacter() {
>     ComplexFormat format = new ComplexFormat();
>     String invalidComplex = "3 + 5";
>     
>     assertThrows(MathParseException.class, () -> {
>         format.parse(invalidComplex);
>     }, "Parsing '3 + 5' should throw MathParseException due to missing 
> imaginary character 'i'");
> } {code}
> *Test Result:*
> {code:java}
> org.opentest4j.AssertionFailedError: Expected 
> org.apache.commons.math4.legacy.exception.MathParseException to be thrown, 
> but nothing was thrown.{code}
> *Root Cause Analysis:*
> The bug occurs due to incomplete error handling in the interaction between 
> {{parse(String)}} and {{parse(String, ParsePosition)}} methods.
> When parsing "3 + 5":
>  # The parser successfully reads "3" (real part), advancing the index from 0 
> to 1
>  # It reads "+" (operator), advancing the index further
>  # It reads "5" (imaginary coefficient), advancing the index to 5
>  # It fails to find the imaginary character 'i'
>  # At this point, {{parse(String, ParsePosition)}} returns {{null}} BUT does 
> not reset the position index
> {code:java}
> // In parse(String source, ParsePosition pos)
> // parse imaginary character
> if (!CompositeFormat.parseFixedstring(source, getImaginaryCharacter(), pos)) {
>     return null;  // Bug: position index is not reset to initialIndex
> }{code}
>       6. Back in {{{}parse(String){}}}, the check {{if 
> (parsePosition.getIndex() == 0)}} evaluates to false (index is 5)
>       7. The method returns {{null}} without throwing an exception



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to