← Назад к вопросам

Преобразование строки в число без parseInt

1.2 Junior🔥 151 комментариев
#Другое#Основы Java

Условие

Напишите программу для преобразования строки в целое число без использования Integer.parseInt() и подобных методов.

Примеры

  • "123" → 123
  • "-456" → -456
  • " 789 " → 789
  • "2147483647" → 2147483647
  • "abc" → выбросить исключение

Требования

  • Обработайте знак (+ или -)
  • Обработайте пробелы в начале и конце
  • Обработайте переполнение int
  • Выбросьте исключение для некорректного ввода

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Преобразование строки в целое число без parseInt()

Это классическая задача на собеседованиях, которая проверяет понимание работы с символами, обработку исключений и граничные случаи. Решение требует реализации алгоритма парсинга с нуля.

Пошаговый алгоритм

  1. Trim — удалить пробелы в начале и конце
  2. Проверка пустоты — если строка пуста, выбросить исключение
  3. Обработка знака — определить, положительное или отрицательное число
  4. Валидация символов — проверить, что все оставшиеся символы цифры
  5. Конвертация — перевести каждую цифру в число и накопить результат
  6. Проверка переполнения — убедиться, что результат не выходит за границы int

Основное решение

public class StringToInteger {
    
    public static int stringToInteger(String str) {
        if (str == null) {
            throw new IllegalArgumentException("String cannot be null");
        }
        
        str = str.trim();
        
        if (str.isEmpty()) {
            throw new IllegalArgumentException("String cannot be empty");
        }
        
        int sign = 1;
        int index = 0;
        
        if (str.charAt(0) == '+' || str.charAt(0) == '-') {
            if (str.charAt(0) == '-') {
                sign = -1;
            }
            index = 1;
        }
        
        if (index == str.length()) {
            throw new IllegalArgumentException("No digits found after sign");
        }
        
        int result = 0;
        final int INT_MAX = Integer.MAX_VALUE;
        final int INT_MIN = Integer.MIN_VALUE;
        
        while (index < str.length()) {
            char c = str.charAt(index);
            
            if (!Character.isDigit(c)) {
                throw new IllegalArgumentException(
                    "Invalid character at index " + index + ": " + c
                );
            }
            
            int digit = c - '0';
            
            if (sign == 1) {
                if (result > INT_MAX / 10 || 
                    (result == INT_MAX / 10 && digit > 7)) {
                    throw new ArithmeticException("Integer overflow");
                }
            } else {
                if (result > -(INT_MIN / 10) || 
                    (result == -(INT_MIN / 10) && digit > 8)) {
                    throw new ArithmeticException("Integer underflow");
                }
            }
            
            result = result * 10 + digit;
            index++;
        }
        
        return sign * result;
    }
}

Тестирование

public class Main {
    public static void main(String[] args) {
        testCase("123", 123);
        testCase("-456", -456);
        testCase("  789  ", 789);
        testCase("0", 0);
        testCase("+42", 42);
        testCase("2147483647", Integer.MAX_VALUE);
        testCase("-2147483648", Integer.MIN_VALUE);
        
        testError("");
        testError("  ");
        testError("abc");
        testError("12a34");
        testError("-");
        testError("+");
        testError("2147483648");
        testError("-2147483649");
    }
    
    private static void testCase(String input, int expected) {
        try {
            int result = StringToInteger.stringToInteger(input);
            System.out.println("OK: '" + input + "' = " + result);
        } catch (Exception e) {
            System.out.println("ERROR: '" + input + "' -> " + e.getMessage());
        }
    }
    
    private static void testError(String input) {
        try {
            int result = StringToInteger.stringToInteger(input);
            System.out.println("FAIL: '" + input + "' should error but got " + result);
        } catch (Exception e) {
            System.out.println("OK: '" + input + "' -> " + e.getMessage());
        }
    }
}

Альтернативное решение с дополнительной обработкой

public class StringToIntegerV2 {
    
    public static int stringToInteger(String str) {
        if (str == null || str.isEmpty()) {
            throw new IllegalArgumentException("Invalid input");
        }
        
        str = str.trim();
        if (str.isEmpty()) {
            throw new IllegalArgumentException("String is empty after trim");
        }
        
        int sign = 1;
        int index = 0;
        
        char firstChar = str.charAt(0);
        if (firstChar == '-') {
            sign = -1;
            index = 1;
        } else if (firstChar == '+') {
            index = 1;
        }
        
        if (index >= str.length()) {
            throw new IllegalArgumentException("No digits found");
        }
        
        int result = 0;
        
        for (int i = index; i < str.length(); i++) {
            char c = str.charAt(i);
            
            if (c < '0' || c > '9') {
                throw new IllegalArgumentException("Invalid digit: " + c);
            }
            
            int digit = c - '0';
            
            int limit = Integer.MAX_VALUE / 10;
            if (sign == 1) {
                if (result > limit || 
                    (result == limit && digit > Integer.MAX_VALUE % 10)) {
                    throw new ArithmeticException("Result overflow");
                }
            } else {
                if (result > -Integer.MIN_VALUE / 10 || 
                    (result == -Integer.MIN_VALUE / 10 && 
                     digit > -(Integer.MIN_VALUE % 10))) {
                    throw new ArithmeticException("Result underflow");
                }
            }
            
            result = result * 10 + digit;
        }
        
        return sign * result;
    }
}

Объяснение проверки переполнения

Неправильно (переполнение уже произошло):

result = result * 10 + digit;
if (result > Integer.MAX_VALUE) {
    throw new Exception();
}

Правильно (проверяем перед умножением):

if (result > Integer.MAX_VALUE / 10 || 
    (result == Integer.MAX_VALUE / 10 && digit > 7)) {
    throw new Exception();
}
result = result * 10 + digit;

Почему digit > 7 при MAX_VALUE = 2147483647?

  • Integer.MAX_VALUE / 10 = 214748364
  • Integer.MAX_VALUE % 10 = 7
  • Если result == 214748364 и приходит цифра > 7, то overflow

Сложность

  • Временная сложность: O(n), где n — длина строки
  • Пространственная сложность: O(1)

Ключевые моменты

  1. Обработка null и пустых строк
  2. Обработка пробелов (trim)
  3. Обработка знака (+ и -)
  4. Валидация символов (все ли это цифры)
  5. Проверка переполнения — самый сложный момент
  6. Использование Character.isDigit()
  7. Преобразование char в int через вычитание '0'

Это решение демонстрирует глубокое понимание работы с числами и граничными случаями.

Преобразование строки в число без parseInt | PrepBro