Repository: TheAlgorithms/Java
Pull request #5324 (2024-08-14 20:47:05)

refactor: `atoi`
Refactoring atoi implementation.
Reducing complexity.
Improving tests coverage.

<!--
Thank you for your contribution!
In order to reduce the number of notifications sent to the maintainers, please:
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
- make sure that all of the CI checks pass,
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
-->

<!-- For completed items, change [ ] to [x] -->

- [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
- [x] This pull request is all my own work -- I have not plagiarized it.
- [x] All filenames are in PascalCase.
- [x] All functions and variable names follow Java naming conventions.
- [x] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
- [x] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5324?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 42.48%. Comparing base [(`8d0dd3e`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/8d0dd3ef32d78a767d81ac0f71ade70e524bb1d1?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) to head [(`bdbee45`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/bdbee4504942354fe09e780091362597dbb73ac1?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #5324      +/-   ##
============================================
+ Coverage     42.38%   42.48%   +0.10%     
- Complexity     2632     2637       +5     
============================================
  Files           522      522              
  Lines         15527    15504      -23     
  Branches       2963     2953      -10     
============================================
+ Hits           6581     6587       +6     
+ Misses         8649     8633      -16     
+ Partials        297      284      -13     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5324?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).


Patch:
diff --git a/src/main/java/com/thealgorithms/strings/MyAtoi.java b/src/main/java/com/thealgorithms/strings/MyAtoi.java
index f58ab1ac..5a7c2ce5 100644
--- a/src/main/java/com/thealgorithms/strings/MyAtoi.java
+++ b/src/main/java/com/thealgorithms/strings/MyAtoi.java
@@ -1,76 +1,65 @@
-// Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer
-// (similar to C/C++'s atoi function). Here is my implementation
-
 package com.thealgorithms.strings;
 
+/**
+ * A utility class that provides a method to convert a string to a 32-bit signed integer (similar to C/C++'s atoi function).
+ */
 public final class MyAtoi {
     private MyAtoi() {
     }
-    public static int myAtoi(String s) {
-        s = s.trim();
-        char[] char1 = s.toCharArray();
-        String number = "";
-        boolean negative = false;
-        boolean zero = false;
-        boolean isDigit = false;
 
-        for (char ch : char1) {
-            if (Character.isDigit(ch)) {
-                if (number.length() > 1 && !isDigit) {
-                    number = "0";
-                    break;
-                }
-                isDigit = true;
-                if (zero) {
-                    number = "0";
-                    break;
-                }
-                if (ch >= '0' && ch <= '9') {
-                    number += ch;
-                }
-            } else if (ch == '-' && !isDigit) {
-                number += "0";
-                negative = true;
-            } else if (ch == '+' && !isDigit) {
-                number += "0";
-            } else if (ch == '.' && isDigit) {
-                break;
-            } else if (ch == '.') {
-                zero = true;
-            } else {
-                if (!isDigit) {
-                    number = "0";
-                }
-                break;
-            }
+    /**
+     * Converts the given string to a 32-bit signed integer.
+     * The conversion discards any leading whitespace characters until the first non-whitespace character is found.
+     * Then, it takes an optional initial plus or minus sign followed by as many numerical digits as possible and interprets them as a numerical value.
+     * The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
+     *
+     * If the number is out of the range of a 32-bit signed integer:
+     * - Returns {@code Integer.MAX_VALUE} if the value exceeds {@code Integer.MAX_VALUE}.
+     * - Returns {@code Integer.MIN_VALUE} if the value is less than {@code Integer.MIN_VALUE}.
+     *
+     * If no valid conversion could be performed, a zero is returned.
+     *
+     * @param s the string to convert
+     * @return the converted integer, or 0 if the string cannot be converted to a valid integer
+     */
+    public static int myAtoi(String s) {
+        if (s == null || s.isEmpty()) {
+            return 0;
         }
 
-        if (!isDigit) {
+        s = s.trim();
+        int length = s.length();
+        if (length == 0) {
             return 0;
         }
 
-        number = number.replaceFirst("^0+(?!$)", "");
+        int index = 0;
+        boolean negative = false;
+
+        // Check for the sign
+        if (s.charAt(index) == '-' || s.charAt(index) == '+') {
+            negative = s.charAt(index) == '-';
+            index++;
+        }
 
-        if (number.length() > 10 && negative) {
-            return -2147483648;
-        } else if (number.length() > 10) {
-            return 2147483647;
-        } else if (number.length() == 10 && negative) {
-            double db1 = Double.parseDouble(number);
-            if (db1 >= 2147483648d) {
-                return -2147483648;
+        int number = 0;
+        while (index < length) {
+            char ch = s.charAt(index);
+            if (!Character.isDigit(ch)) {
+                break;
             }
-        } else if (number.length() == 10) {
-            double db1 = Double.parseDouble(number);
-            if (db1 > (2147483647)) {
-                return 2147483647;
+
+            int digit = ch - '0';
+
+            // Check for overflow
+            if (number > (Integer.MAX_VALUE - digit) / 10) {
+                return negative ? Integer.MIN_VALUE : Integer.MAX_VALUE;
             }
-        }
 
-        if (negative) {
-            return Integer.parseInt(number) * -1;
+            number = number * 10 + digit;
+            index++;
         }
 
-        return Integer.parseInt(number);
+        return negative ? -number : number;
     }
 }


Test patch:
diff --git a/src/test/java/com/thealgorithms/strings/MyAtoiTest.java b/src/test/java/com/thealgorithms/strings/MyAtoiTest.java
index 45f91585..8d235491 100644
--- a/src/test/java/com/thealgorithms/strings/MyAtoiTest.java
+++ b/src/test/java/com/thealgorithms/strings/MyAtoiTest.java
@@ -3,41 +3,41 @@ package com.thealgorithms.strings;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 
 public class MyAtoiTest {
 
-    @Test
-    void testOne() {
-        assertEquals(42, MyAtoi.myAtoi("42"));
-    }
-
-    @Test
-    void testTwo() {
-        assertEquals(-42, MyAtoi.myAtoi("   -42"));
+    @ParameterizedTest
+    @CsvSource({"'42', 42", "'   -42', -42", "'4193 with words', 4193", "'words and 987', 0", "'-91283472332', -2147483648", "'21474836460', 2147483647", "'   +123', 123", "'', 0", "'    ', 0", "'-2147483648', -2147483648", "'+2147483647', 2147483647", "'   -0012a42', -12",
+        "'9223372036854775808', 2147483647", "'-9223372036854775809', -2147483648", "'3.14159', 3", "'  -0012', -12", "'  0000000000012345678', 12345678", "'  -0000000000012345678', -12345678", "'  +0000000000012345678', 12345678", "'0', 0", "'+0', 0", "'-0', 0"})
+    void
+    testMyAtoi(String input, int expected) {
+        assertEquals(expected, MyAtoi.myAtoi(input));
     }
 
     @Test
-    void testThree() {
-        assertEquals(4193, MyAtoi.myAtoi("4193 with words"));
+    void testNullInput() {
+        assertEquals(0, MyAtoi.myAtoi(null));
     }
 
     @Test
-    void testFour() {
-        assertEquals(0, MyAtoi.myAtoi("0"));
+    void testSinglePlus() {
+        assertEquals(0, MyAtoi.myAtoi("+"));
     }
 
     @Test
-    void testFive() {
-        assertEquals(5678, MyAtoi.myAtoi("5678"));
+    void testSingleMinus() {
+        assertEquals(0, MyAtoi.myAtoi("-"));
     }
 
     @Test
-    void testSix() {
-        assertEquals(42, MyAtoi.myAtoi("+42"));
+    void testIntegerMinBoundary() {
+        assertEquals(Integer.MIN_VALUE, MyAtoi.myAtoi("-2147483648"));
     }
 
     @Test
-    void testSeven() {
-        assertEquals(0, MyAtoi.myAtoi("  +0   "));
+    void testIntegerMaxBoundary() {
+        assertEquals(Integer.MAX_VALUE, MyAtoi.myAtoi("2147483647"));
     }
 }