Marc Hauschildt
Web Technologies and Computer Software Development Instructor at Kirkwood Community College in Cedar Rapids, IA.
Week 4
Software Development Life Cycle, Steps 4-5
Fraction Project
/**
* Splits the user input string into three parts: first fraction, operator, and second fraction.
*
* @param input the raw input string from the user.
* @return a String array of size 3.
* @throws IllegalArgumentException if the input format or operator is invalid.
*/
private static String[] splitCalculation(String input) {
return new String[]{};
}@Test
@DisplayName("Test splitCalculation with addition operator")
void splitCalculationWithAddition() {
// Arrange
String input = "1/2 + 3/4";
String[] expected = {"1/2", "+", "3/4"};
// Act
String[] actual = FractionCalculator.splitCalculation(input);
// Assert
assertArrayEquals(expected, actual);
}@Test
@DisplayName("Test splitCalculation with subtraction operator and mixed numbers")
void splitCalculationWithSubtractionAndMixedNumbers() {
// Arrange
String input = "3 1/4 - 1/2";
String[] expected = {"3 1/4", "-", "1/2"};
// Act
String[] actual = FractionCalculator.splitCalculation(input);
// Assert
assertArrayEquals(expected, actual);
}@Test
@DisplayName("Test splitCalculation with multiplication and negative numbers")
void splitCalculationWithMultiplicationAndNegatives() {
// Arrange
String input = "-5 * -2 1/3";
String[] expected = {"-5", "*", "-2 1/3"};
// Act
String[] actual = FractionCalculator.splitCalculation(input);
// Assert
assertArrayEquals(expected, actual);
}@Test
@DisplayName("Test splitCalculation with division operator")
void splitCalculationWithDivision() {
// Arrange
String input = "10/3 / 5";
String[] expected = {"10/3", "/", "5"};
// Act
String[] actual = FractionCalculator.splitCalculation(input);
// Assert
assertArrayEquals(expected, actual);
}@Test
@DisplayName("Test splitCalculation with extra spaces in input")
void splitCalculationWithExtraSpaces() {
// Arrange
String input = " 1/2 + 3/4 ";
String[] expected = {"1/2", "+", "3/4"};
// Act
String[] actual = FractionCalculator.splitCalculation(input);
// Assert
assertArrayEquals(expected, actual);
}@Test
@DisplayName("Test splitCalculation with no spaces around operator should throw exception")
void splitCalculationWithNoSpacesAroundOperator() {
// Arrange
String input = "1/2+3/4";
// Act & Assert
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
FractionCalculator.splitCalculation(input);
});
String expectedMessage = "Invalid format. Ensure operator (+, -, *, /) has a space on both sides.";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
}@Test
@DisplayName("Test splitCalculation with no spaces around operator should throw exception")
void splitCalculationWithNoSpacesAroundOperator() {
// Arrange
String input = "1/2+3/4";
// Act & Assert
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
FractionCalculator.splitCalculation(input);
});
String expectedMessage = "Invalid format.";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
}@Test
@DisplayName("Test splitCalculation with unknown operator should throw exception")
void splitCalculationWithUnknownOperator() {
// Arrange
String input = "1/2 ^ 3/4";
// Act & Assert
assertThrows(IllegalArgumentException.class, () -> {
FractionCalculator.splitCalculation(input);
});
}@Test
@DisplayName("Test splitCalculation with missing first fraction should throw exception")
void splitCalculationWithMissingFirstFraction() {
// Arrange
String input = " + 3/4";
// Act & Assert
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
FractionCalculator.splitCalculation(input);
});
String expectedMessage = "Missing the first fraction";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
}
@Test
@DisplayName("Test splitCalculation with missing second fraction should throw exception")
void splitCalculationWithMissingSecondFraction() {
// Arrange
String input = "1/2 + ";
// Act & Assert
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
FractionCalculator.splitCalculation(input);
});
String expectedMessage = "Missing the second fraction";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
}@Test
void splitCalculationWithAddition() {
// Arrange - define input and expected outputs
String input = "1/2 + 3/4";
String[] expected = {"1/2", "+", "3/4"};
// Act - call the method to be tested
String[] actual = FractionCalculator.splitCalculation(input);
// Assert - call one of the assert methods
assertArrayEquals(expected, actual);
}
@Test
void splitCalculationWithSubtraction() {
// Arrange - define input and expected outputs
String input = "3 1/4 - 1/2";
String[] expected = {"3 1/4", "-", "1/2"};
// Act - call the method to be tested
String[] actual = FractionCalculator.splitCalculation(input);
// Assert - call one of the assert methods
assertArrayEquals(expected, actual);
}
@Test
void splitCalculationWithMultiplication() {
// Arrange - define input and expected outputs
String input = "-5 * -2 1/3";
String[] expected = {"-5", "*", "-2 1/3"};
// Act - call the method to be tested
String[] actual = FractionCalculator.splitCalculation(input);
// Assert - call one of the assert methods
assertArrayEquals(expected, actual);
}
@Test
void splitCalculationWithDivision() {
// Arrange - define input and expected outputs
String input = "10/3 / 5";
String[] expected = {"10/3", "/", "5"};
// Act - call the method to be tested
String[] actual = FractionCalculator.splitCalculation(input);
// Assert - call one of the assert methods
assertArrayEquals(expected, actual);
}
@Test
void splitCalculationTooManySpaces() {
// Arrange - define input and expected outputs
String input = " 10/3 / 5 ";
String[] expected = {"10/3", "/", "5"};
// Act - call the method to be tested
String[] actual = FractionCalculator.splitCalculation(input);
// Assert - call one of the assert methods
assertArrayEquals(expected, actual);
}
@Test
void splitCalculationNoSpacesAroundOperator() {
// Arrange - define input and expected outputs
String input = "10/3/5";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> FractionCalculator.splitCalculation(input));
// Arrange
String expectedError = "Invalid format";
// Act
String actualError = e.getMessage();
// Assert
assertTrue(actualError.contains(expectedError));
}
@Test
void splitCalculationInvalidOperator1() {
// Arrange - define input and expected outputs
String input = "10/3 ! 5";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> FractionCalculator.splitCalculation(input));
// Arrange
String expectedError = "Invalid format";
// Act
String actualError = e.getMessage();
// Assert
assertTrue(actualError.contains(expectedError));
}
@Test
void splitCalculationInvalidOperator2() {
// Arrange - define input and expected outputs
String input = "10/3 x 5";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> FractionCalculator.splitCalculation(input));
// Arrange
String expectedError = "Invalid format";
// Act
String actualError = e.getMessage();
// Assert
assertTrue(actualError.contains(expectedError));
}
@Test
void splitCalculationFirstFractionMissing() {
// Arrange - define input and expected outputs
String input = " / 5";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> FractionCalculator.splitCalculation(input));
// Arrange
String expectedError = "Missing fraction";
// Act
String actualError = e.getMessage();
// Assert
assertTrue(actualError.contains(expectedError));
}
@Test
void splitCalculationSecondFractionMissing() {
// Arrange - define input and expected outputs
String input = "5 / ";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> FractionCalculator.splitCalculation(input));
// Arrange
String expectedError = "Missing fraction";
// Act
String actualError = e.getMessage();
// Assert
assertTrue(actualError.contains(expectedError));
}@Test
void splitInputWithAddition() {
// Arrange
String input = "1/2 + 3/4";
String[] expected = {"1/2", "+", "3/4"};
// Act
String[] actual = MarcsFractionCalculator.splitInput(input);
// Assert
assertArrayEquals(expected, actual);
}
@Test
@DisplayName("Test splitCalculation with subtraction operator and mixed numbers")
void splitCalculationWithSubtractionAndMixedNumbers() {
// Arrange
String input = "3 1/4 - 1/2";
String[] expected = {"3 1/4", "-", "1/2"};
// Act
String[] actual = MarcsFractionCalculator.splitInput(input);
// Assert
assertArrayEquals(expected, actual);
}
@Test
@DisplayName("Test splitCalculation with multiplication and negative numbers")
void splitCalculationWithMultiplicationAndNegatives() {
// Arrange
String input = "-5 * -2 1/3";
String[] expected = {"-5", "*", "-2 1/3"};
// Act
String[] actual = MarcsFractionCalculator.splitInput(input);
// Assert
assertArrayEquals(expected, actual);
}
@Test
@DisplayName("Test splitCalculation with division operator")
void splitCalculationWithDivision() {
// Arrange
String input = "10/3 / 5";
String[] expected = {"10/3", "/", "5"};
// Act
String[] actual = MarcsFractionCalculator.splitInput(input);
// Assert
assertArrayEquals(expected, actual);
}
@Test
@DisplayName("Test splitCalculation with extra spaces in input")
void splitCalculationWithExtraSpaces() {
// Arrange
String input = " 1/2 + 3/4 ";
String[] expected = {"1/2", "+", "3/4"};
// Act
String[] actual = MarcsFractionCalculator.splitInput(input);
// Assert
assertArrayEquals(expected, actual);
}
@Test
void splitInputWithNoSpacesAroundOperator() {
//Arrange
String input = "1/2+3/4";
// Act and Assert
Executable actual = () -> MarcsFractionCalculator.splitInput(input);
// Assert
Exception e = assertThrows(IllegalArgumentException.class, actual);
// Arrange
String expectedErrorMsg = "Invalid format";
//Act
String actualErrorMsg = e.getMessage();
assertTrue(actualErrorMsg.contains(expectedErrorMsg));
}
@Test
void splitInputWithInvalidOperator() {
//Arrange
String input = "1/2 ! 3/4";
// Act and Assert
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.splitInput(input));
}
@Test
void splitInputWithInvalidFraction1() {
//Arrange
String input = " + 3/4";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.splitInput(input));
//Arrage
String expectedErrorMsg = "First fraction is required";
//Act
String actualErrorMsg = e.getMessage();
//Assert
assertEquals(expectedErrorMsg, actualErrorMsg);
}
@Test
void splitInputWithInvalidFraction2() {
//Arrange
String input = "1/2 + ";
// Act and Assert
Exception e = assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.splitInput(input));
//Arrage
String expectedErrorMsg = "Second fraction is required";
//Act
String actualErrorMsg = e.getMessage();
//Assert
assertEquals(expectedErrorMsg, actualErrorMsg);
}/**
* Splits the user input string into three parts: first fraction, operator, and second fraction.
*
* @param input the raw input string from the user.
* @return a String array of size 3.
* @throws IllegalArgumentException if the input format or operator is invalid.
*/
private static String[] splitCalculation(String input) {
String operator = null;
int operatorIndex = -1;
// Find the operator with spaces around it to correctly handle negative numbers
if (input.contains(" + ")) {
operator = "+";
operatorIndex = input.indexOf(" + ");
} else if (input.contains(" - ")) {
operator = "-";
operatorIndex = input.indexOf(" - ");
} else if (input.contains(" * ")) {
operator = "*";
operatorIndex = input.indexOf(" * ");
} else if (input.contains(" / ")) {
operator = "/";
operatorIndex = input.indexOf(" / ");
}
if (operator == null) {
throw new IllegalArgumentException("Invalid format. Ensure operator (+, -, *, /) has a space on both sides.");
}
return new String[]{};
}/**
* Splits the user input string into three parts: first fraction, operator, and second fraction.
*
* @param input the raw input string from the user.
* @return a String array of size 3.
* @throws IllegalArgumentException if the input format or operator is invalid.
*/
private static String[] splitCalculation(String input) {
String operator = null;
int operatorIndex = -1;
// Find the operator with spaces around it to correctly handle negative numbers
if (input.contains(" + ")) {
operator = "+";
operatorIndex = input.indexOf(" + ");
} else if (input.contains(" - ")) {
operator = "-";
operatorIndex = input.indexOf(" - ");
} else if (input.contains(" * ")) {
operator = "*";
operatorIndex = input.indexOf(" * ");
} else if (input.contains(" / ")) {
operator = "/";
operatorIndex = input.indexOf(" / ");
}
if (operator == null) {
throw new IllegalArgumentException("Invalid format. Ensure operator (+, -, *, /) has a space on both sides.");
}
String fractionStr1 = input.substring(0, operatorIndex).trim();
String fractionStr2 = input.substring(operatorIndex + 3).trim(); // +3 to skip operator and spaces
if (fractionStr1.isEmpty()) {
throw new IllegalArgumentException("Missing the first fraction in the calculation.");
}
if (fractionStr2.isEmpty()) {
throw new IllegalArgumentException("Missing the second fraction in the calculation.");
}
return new String[]{fractionStr1, operator, fractionStr2};
}/**
* Splits the user input string into three parts: fraction 1, operator, fraction 2
* @param input the raw input string from the user
* @return a String[] array of size 3
* @throws IllegalArgumentException if the input format or operator is invalid
*/
public static String[] splitCalculation(String input) {
String operator = "";
int operatorIndex = -1;
if(input.contains(" + ")) {
operator = "+";
operatorIndex = input.indexOf(" + ");
} else if(input.contains(" - ")) {
operator = "-";
operatorIndex = input.indexOf(" - ");
} else if(input.contains(" * ")) {
operator = "*";
operatorIndex = input.indexOf(" * ");
} else if(input.contains(" / ")) {
operator = "/";
operatorIndex = input.indexOf(" / ");
}
if(operatorIndex == -1) {
throw new IllegalArgumentException("Invalid format. Ensure operator (+, -, *, /) has a space on both sides.");
}
String fraction1 = input.substring(0, operatorIndex).trim();
String fraction2 = input.substring(operatorIndex + 3).trim();
if(fraction1.isEmpty()) {
throw new IllegalArgumentException("Missing fraction 1.");
}
if(fraction2.isEmpty()) {
throw new IllegalArgumentException("Missing fraction 2.");
}
return new String[]{fraction1, operator, fraction2};
}/**
* Split the user input into three parts: fraction 1, operator, fraction 2
*
* @param input the raw input string from the user
* @return String[] array with three Strings
* @throws IllegalArgumentException if input or operator are invalid
*/
public static String[] splitInput(String input) {
String operator = "";
int operatorIndex = -1;
if(input.contains(" + ")) {
operator = "+";
operatorIndex = input.indexOf(" + ");
} else if(input.contains(" - ")) {
operator = "-";
operatorIndex = input.indexOf(" - ");
} else if(input.contains(" * ")) {
operator = "*";
operatorIndex = input.indexOf(" * ");
} else if(input.contains(" / ")) {
operator = "/";
operatorIndex = input.indexOf(" / ");
}
if(operatorIndex == -1) {
throw new IllegalArgumentException("Invalid format. Ensure operator (+, -, *, /) has space on both sides.");
}
String fraction1 = input.substring(0, operatorIndex).trim();
String fraction2 = input.substring(operatorIndex + 3).trim();
if(fraction1.isEmpty()) {
throw new IllegalArgumentException("First fraction is required");
}
if(fraction2.isEmpty()) {
throw new IllegalArgumentException("Second fraction is required");
}
return new String[]{fraction1, operator, fraction2};
}/**
* Parses a string into a Fraction object.
* Handles whole numbers, fractions, and mixed numbers.
*
* @param str the string to parse.
* @return a Fraction object representing the parsed string.
* @throws NumberFormatException if the number parts are not valid integers.
* @throws IllegalArgumentException if the fraction format is invalid.
*/
public static Fraction parseFraction(String str) {
return null;
}@Test
@DisplayName("Test parseFraction with a positive whole number")
void parseFractionWithPositiveWholeNumber() {
Fraction f = FractionCalculator.parseFraction("5");
assertEquals(5, f.getNumerator());
assertEquals(1, f.getDenominator());
}
@Test
@DisplayName("Test parseFraction with a negative whole number")
void parseFractionWithNegativeWholeNumber() {
Fraction f = FractionCalculator.parseFraction("-10");
assertEquals(-10, f.getNumerator());
assertEquals(1, f.getDenominator());
}@Test
@DisplayName("Test parseFraction with a simple fraction")
void parseFractionWithSimpleFraction() {
Fraction f = FractionCalculator.parseFraction("3/4");
assertEquals(3, f.getNumerator());
assertEquals(4, f.getDenominator());
}
@Test
@DisplayName("Test parseFraction with a negative improper fraction")
void parseFractionWithNegativeImproperFraction() {
Fraction f = FractionCalculator.parseFraction("-7/2");
assertEquals(-7, f.getNumerator());
assertEquals(2, f.getDenominator());
}@Test
@DisplayName("Test parseFraction with a positive mixed number")
void parseFractionWithPositiveMixedNumber() {
Fraction f = FractionCalculator.parseFraction("2 1/3"); // 2*3+1 = 7
assertEquals(7, f.getNumerator());
assertEquals(3, f.getDenominator());
}
@Test
@DisplayName("Test parseFraction with a negative mixed number")
void parseFractionWithNegativeMixedNumber() {
Fraction f = FractionCalculator.parseFraction("-3 1/4"); // -3*4-1 = -13
assertEquals(-13, f.getNumerator());
assertEquals(4, f.getDenominator());
}@Test
@DisplayName("Test parseFraction with text should throw exception")
void parseFractionWithText_ThrowsException() {
assertThrows(NumberFormatException.class, () -> FractionCalculator.parseFraction("hello"));
}
@Test
@DisplayName("Test parseFraction with invalid mixed number format should throw exception")
void parseFractionWithInvalidMixedNumber_ThrowsException() {
Exception e = assertThrows(IllegalArgumentException.class, () -> FractionCalculator.parseFraction("1 2 3"));
assertTrue(e.getMessage().contains("Invalid mixed number format"));
}
@Test
@DisplayName("Test parseFraction with zero denominator should throw exception")
void parseFractionWithZeroDenominator_ThrowsException() {
Exception e = assertThrows(ArithmeticException.class, () -> FractionCalculator.parseFraction("5/0"));
assertTrue(e.getMessage().contains("Denominator cannot be zero"));
}@Test
void parseFractionPositiveWholeNumber() {
// Arrange
String input = "5";
Fraction expected = new Fraction(5, 1);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionNegativeWholeNumber() {
Fraction actual = FractionCalculator.parseFraction("-5");
assertEquals(-5, actual.getNumerator());
assertEquals(1, actual.getDenominator());
}
@Test
void parseFractionSimpleFraction() {
// Arrange
String input = "5/7";
Fraction expected = new Fraction(5, 7);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionNegativeImproperFraction() {
// Arrange
String input = "-5/3";
Fraction expected = new Fraction(-5, 3);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionMixedFraction() {
// Arrange
String input = "2 1/3";
Fraction expected = new Fraction(7, 3);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionNegativeMixedFraction() {
// Arrange
String input = "-3 1/4";
Fraction expected = new Fraction(-13, 4);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionWithText() {
// One-liner
assertThrows(IllegalArgumentException.class, () -> FractionCalculator.parseFraction("X"));
// Arrange
String input = "X";
Class expected = IllegalArgumentException.class;
// Act
Executable actual = () -> FractionCalculator.parseFraction(input);
// Assert
assertThrows(expected, actual);
}
@Test
void parseFractionInvalidSlash() {
// one-liner
assertThrows(IllegalArgumentException.class, () -> FractionCalculator.parseFraction("1 2"));
// Arrange
String input = "1 2";
Class expected = IllegalArgumentException.class;
// Act
Executable actual = () -> FractionCalculator.parseFraction(input);
// Assert
assertThrows(expected, actual);
}
@Test
void parseFractionDivideByZero() {
// one-liner
assertThrows(IllegalArgumentException.class, () -> FractionCalculator.parseFraction("1/0"));
// Arrange
String input = "1/0";
Class expected = IllegalArgumentException.class;
// Act
Executable actual = () -> FractionCalculator.parseFraction(input);
// Assert
assertThrows(expected, actual);
}
@Test
void parseFractionInvalidNumerator() {
// one-liner
assertThrows(IllegalArgumentException.class, () -> FractionCalculator.parseFraction("N/1"));
// Arrange
String input = "N/1";
Class expected = IllegalArgumentException.class;
// Act
Executable actual = () -> FractionCalculator.parseFraction(input);
// Assert
assertThrows(expected, actual);
}
@Test
void parseFractionInvalidDenominator() {
// one-liner
assertThrows(IllegalArgumentException.class, () -> FractionCalculator.parseFraction("1/N"));
// Arrange
String input = "1/N";
Class expected = IllegalArgumentException.class;
// Act
Executable actual = () -> FractionCalculator.parseFraction(input);
// Assert
assertThrows(expected, actual);
}
@Test
void parseFractionNegativeDenominator() {
// Arrange
String input = "1/-3";
Fraction expected = new Fraction(-1, 3);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionNegativeNumeratorMixedNumber() {
// Arrange
String input = "1 -1/3";
Fraction expected = new Fraction(-4, 3);
// Act
Fraction actual = FractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}@Test
void parseFractionWithPositiveWholeNumber() {
// Arrange
String input = "5";
Fraction expected = new Fraction(5,1);
// Act
Fraction actual = MarcsFractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionWithNegativeWholeNumber() {
Fraction f = MarcsFractionCalculator.parseFraction("-1");
assertEquals(-1, f.getNumerator());
assertEquals(1, f.getDenominator());
}
@Test
void parseFractionWithProperPositive() {
// Arrange
String input = "3/4";
Fraction expected = new Fraction(3,4);
// Act
Fraction actual = MarcsFractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionWithProperNegative() {
// Arrange
String input = "-3/4";
Fraction expected = new Fraction(-3,4);
// Act
Fraction actual = MarcsFractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
// Arrange
input = "3/-4";
expected = new Fraction(-3,4);
// Act
actual = MarcsFractionCalculator.parseFraction(input);
// Assert
assertEquals(expected, actual);
}
@Test
void parseFractionWithPositiveMixedNumber() {
Fraction f = MarcsFractionCalculator.parseFraction("2 1/3");
assertEquals(7, f.getNumerator());
assertEquals(3, f.getDenominator());
}
@Test
void parseFractionWithNegativeMixedNumber() {
Fraction f = MarcsFractionCalculator.parseFraction("-2 1/3");
assertEquals(-7, f.getNumerator());
assertEquals(3, f.getDenominator());
}
@Test
void parseFractionWithNegativeMixedNumber2() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("2 -1/3"));
}
@Test
void parseFractionWithNegativeMixedNumber3() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("2 1/-3"));
}
@Test
void parseFractionInvalidNumber() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("X"), "X is not a valid fraction");
}
@Test
void parseFractionInvalidNumerator() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("X/1"), "X is not a valid fraction");
}
@Test
void parseFractionInvalidDenominator() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("1/X"), "X is not a valid fraction");
}
@Test
void parseFractionInvalidSlash() {
// Arrange
String input = "1 3!4";
Class expected = IllegalArgumentException.class;
// Act
Executable actual = () -> MarcsFractionCalculator.parseFraction(input);
// Assert
assertThrows(expected, actual);
}
@Test
void parseFractionZeroDenominator() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("1/0"));
}
@Test
void parseFractionNonFractionCharacters() {
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("=1/2"));
assertThrows(IllegalArgumentException.class, () -> MarcsFractionCalculator.parseFraction("1/=2"));
}public static Fraction parseFraction(String str) {
if (str.contains(" ")) { // --- Mixed Number (e.g., "1 2/3" or "-2 1/4") ---
Fraction result = null;
return result;
} else if (str.contains("/")) { // --- Proper/Improper Fraction (e.g., "3/4" or "-5/2") ---
Fraction result = null;
return result;
} else { // --- Whole Number (e.g., "5" or "-10") ---
return new Fraction();
}
}public static Fraction parseFraction(String str) {
if (str.contains(" ")) { // --- Mixed Number (e.g., "1 2/3" or "-2 1/4") ---
Fraction result = null;
return result;
} else if (str.contains("/")) { // --- Proper/Improper Fraction (e.g., "3/4" or "-5/2") ---
Fraction result = null;
return result;
} else { // --- Whole Number (e.g., "5" or "-10") ---
int whole = 0;
try {
whole = Integer.parseInt(str);
} catch (NumberFormatException e) {
// This will be thrown if the whole number is not a number
throw new NumberFormatException("Invalid whole number: '" + str + "'");
}
return new Fraction(whole, 1);
}
}public static Fraction parseFraction(String str) {
if (str.contains(" ")) { // --- Mixed Number (e.g., "1 2/3" or "-2 1/4") ---
Fraction result = null;
return result;
} else if (str.contains("/")) { // --- Proper/Improper Fraction (e.g., "3/4" or "-5/2") ---
String[] parts = str.split("/");
int num = 0;
int den = 0;
try {
num = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
// This will be thrown if the numerator is not a number
throw new ArithmeticException("Invalid numerator: '" + parts[0] + "'");
}
try {
den = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
// This will be thrown if the denominator is not a number
throw new ArithmeticException("Invalid denominator: '" + parts[1] + "'");
}
Fraction result = null;
try {
result = new Fraction(num, den);
} catch (ArithmeticException e) {
// This will be thrown if the denominator is zero
throw new ArithmeticException(e.getMessage() + ": '" + str + "'");
}
return result;
} else { // --- Whole Number (e.g., "5" or "-10") ---
int whole = 0;
try {
whole = Integer.parseInt(str);
} catch (NumberFormatException e) {
// This will be thrown if the whole number is not a number
throw new NumberFormatException("Invalid whole number: '" + str + "'");
}
return new Fraction(whole, 1);
}
}public static Fraction parseFraction(String str) {
if (str.contains(" ")) { // --- Mixed Number (e.g., "1 2/3" or "-2 1/4") ---
Fraction result = null;
return result;
} else if (str.contains("/")) { // --- Proper/Improper Fraction (e.g., "3/4" or "-5/2") ---
String[] parts = str.split("/");
int num = 0;
int den = 0;
try {
num = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
// This will be thrown if the numerator is not a number
throw new ArithmeticException("Invalid numerator: '" + str + "'");
}
try {
den = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
// This will be thrown if the denominator is not a number
throw new ArithmeticException("Invalid denominator: '" + str + "'");
}
Fraction result = null;
try {
result = new Fraction(num, den);
} catch (ArithmeticException e) {
// This will be thrown if the denominator is zero
throw new ArithmeticException(e.getMessage() + ": '" + str + "'");
}
return result;
} else { // --- Whole Number (e.g., "5" or "-10") ---
int whole = 0;
try {
whole = Integer.parseInt(str);
} catch (NumberFormatException e) {
// This will be thrown if the whole number is not a number
throw new NumberFormatException("Invalid whole number: '" + str + "'");
}
return new Fraction(whole, 1);
}
}If the limit is a positive value, then the pattern will be applied at most limit - 1 times. 2 means apply it once.
public static Fraction parseFraction(String str) {
if (str.contains(" ")) { // --- Mixed Number (e.g., "1 2/3" or "-2 1/4") ---
String[] parts = str.split(" ", 2);
int whole = 0;
try {
whole = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
// This will be thrown if the first part of the parts array is not a number
// e.g. When entering "- 2 1/4" with a space after the -, the array will be ["-", "2 1/4"]
throw new NumberFormatException("Invalid mixed number format: '" + str + "' (the correct format is '1 2/3' or '-2 1/4')");
}
Fraction result = null;
return result;
} else if (str.contains("/")) { // --- Proper/Improper Fraction (e.g., "3/4" or "-5/2") ---
String[] parts = str.split("/");
int num = Integer.parseInt(parts[0]);
int den = Integer.parseInt(parts[1]);
Fraction result = null;
try {
result = new Fraction(num, den);
} catch (ArithmeticException e) {
// This will be thrown if the denominator is zero
throw new ArithmeticException(e.getMessage() + ": '" + str + "'");
}
return result;
} else { // --- Whole Number (e.g., "5" or "-10") ---
int whole = 0;
try {
whole = Integer.parseInt(str);
} catch (NumberFormatException e) {
// This will be thrown if the whole number is not a number
throw new NumberFormatException("Invalid whole number: '" + str + "'");
}
return new Fraction(whole, 1);
}
}String[] fractionParts = parts[1].split("/", -1);
if (fractionParts.length != 2 || fractionParts[0].isEmpty() || fractionParts[1].isEmpty()) {
throw new IllegalArgumentException("Invalid mixed number format: '" + str + "' (the correct format is '1 2/3' or '-1/3'");
}
String[] parts = str.split("/", -1);
if(parts.length != 2 || parts[0].isEmpty() || parts[1].isEmpty()) {
throw new IllegalArgumentException("Invalid fraction format: '" + str + "'. Fraction format is a/b or whole number");
}/**
* Convert a String into a Fraction object. Handles whole numbers, proper and improper fractions, and mixed number fractions
* @param str is the String to parse
* @return a Fraction object representing the parsed String
* @throws IllegalArgumentException if the String is not a valid fraction
*/
public static Fraction parseFraction(String str) {
Fraction result = null;
if(str.contains(" ")) { // Mixed number fraction like "1 1/2"
String[] parts = str.split(" ");
int whole = 0;
try {
whole = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid whole number. '" + parts[0] + "' (the correct format is '1 2/3')");
}
String[] fractionParts = parts[1].split("/");
int num = 0;
try {
num = Integer.parseInt(fractionParts[0]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid numerator. '" + fractionParts[0] + "' (the correct format is '1 2/3')");
}
int den = 1;
if(fractionParts.length > 1) {
try {
den = Integer.parseInt(fractionParts[1]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid denominator. '" + fractionParts[1] + "' (the correct format is '1 2/3')");
}
} else {
throw new IllegalArgumentException("Invalid denominator (the correct format is '1 2/3')");
}
if(den == 0) {
throw new IllegalArgumentException("Invalid denominator. '" + fractionParts[1] + "' (the correct format is '1 2/3')");
}
// If the fraction part is negative, flip negativity as needed
if(num < 0 && den < 0) {
num *= -1;
den *= -1;
} else if (num < 0 && den > 0) {
num *= -1;
whole *= -1;
} else if (num > 0 && den < 0) {
den *= -1;
whole *= -1;
}
int newNumerator = 0;
if(whole > 0) {
newNumerator = whole * den + num;
} else {
newNumerator = whole * den - num;
}
result = new Fraction(newNumerator, den);
} else if(str.contains("/")) { // Proper or improper fraction like "1/2" or "3/2"
String[] parts = str.split("/");
int num = 0;
try {
num = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid numerator. '" + parts[0] + "'");
}
int den = 0;
try {
den = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid denominator. '" + parts[1] + "'");
}
if(den == 0) {
throw new IllegalArgumentException("Invalid denominator. '" + parts[1] + "'");
}
result = new Fraction(num, den);
} else { // Whole numbers
int whole = 0;
try {
whole = Integer.parseInt(str);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid whole number. '" + str + "'");
}
result = new Fraction(whole, 1);
}
return result;
}/**
* Converts a String into a Fraction object. Handles whole numbers, improper and proper fractions, and mixed numbers
* @param str The String representing a fraction to be parsed
* @return a Fraction object representing the parsed String
* @throws IllegalArgumentException if the String's fraction format is not valid.
*/
public static Fraction parseFraction(String str) {
Fraction result = null;
if(str.contains(" ")) { // Handle Mixed numbers (1 2/3 or -2 1/4)
String[] parts = str.split(" ", 2);
int whole = 0;
// Validate the whole number part
try {
whole = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid whole number: '" + str + "' (the correct format is '1 2/3' or '-1 2/3'");
}
// Validate if the fraction part is missing the forward slash
if(!parts[1].contains("/")) {
throw new IllegalArgumentException("Invalid mixed number format: '" + str + "' (the correct format is '1 2/3' or '-1 2/3'");
}
String[] fractionParts = parts[1].split("/");
int num = 0;
int den = 0;
// Validate if the numerator or denominator are not numbers
try {
num = Integer.parseInt(fractionParts[0]);
} catch(NumberFormatException e) {
throw new IllegalArgumentException("Invalid numerator: '" + str + "'");
}
try {
den = Integer.parseInt(fractionParts[1]);
} catch(NumberFormatException e) {
throw new IllegalArgumentException("Invalid denominator: '" + str + "'");
}
// Convert the results to an improper fraction
if(whole >= 0) {
// Invalid example "2 -1/3 or 2 1/-3)
if(num < 0 || den < 0) {
throw new IllegalArgumentException("Invalid mixed number format: '" + str + "' (the correct format is '1 2/3' or '-1 2/3'");
}
num = whole * den + num;
} else if(whole < 0) {
num = whole * den - num;
}
try {
result = new Fraction(num, den);
} catch(ArithmeticException e) {
// Will have an error if denominator is 0
throw new IllegalArgumentException(e.getMessage() + ": '" + str + "'");
}
} else if(str.contains("/")) { // Handle proper and improper fraction (3/4 or -5/2)
String[] parts = str.split("/");
int num = 0;
int den = 0;
try {
num = Integer.parseInt(parts[0]);
} catch(NumberFormatException e) {
throw new IllegalArgumentException("Invalid numerator: '" + str + "'");
}
try {
den = Integer.parseInt(parts[1]);
} catch(NumberFormatException e) {
throw new IllegalArgumentException("Invalid denominator: '" + str + "'");
}
try {
result = new Fraction(num, den);
} catch(ArithmeticException e) {
// Will have an error if denominator is 0
throw new IllegalArgumentException(e.getMessage() + ": '" + str + "'");
}
} else { // Handle whole numbers (5 or -1)
int whole = 0;
try {
whole = Integer.parseInt(str);
} catch(NumberFormatException e) {
throw new IllegalArgumentException("Invalid whole number: '" + str + "'");
}
result = new Fraction(whole, 1);
}
return result;
}By Marc Hauschildt
Web Technologies and Computer Software Development Instructor at Kirkwood Community College in Cedar Rapids, IA.