Рекурсивная печать от 1 до 1 000 000 в форме слова, исключение - PullRequest
2 голосов
/ 03 апреля 2012

Прежде всего, я хотел бы сказать, что это мой первый пост, и, хотя я никогда не публиковал на StackOverflow.com, люди здесь помогли мне огромное количество, и я хотел бы вернуться и +1 все посты, которые мне помогли.

При этом мне дали задание в классе алгоритмов, где я должен рекурсивно преобразовывать числа от 1 до 1 000 000 в их счетчики слов.

Например, переход от 1 до 1 000 000

one
two
three

...and so on...

one hundred and ninetyseven
one hundred and ninetyeight
one hundred and ninetynine
two hundred

...and so on...

nine hundred and ninetynine thousand nine hundred and ninetyeight
nine hundred and ninetynine thousand nine hundred and ninetynine
one million

У меня код работает до 8,980, а до тестирования до 10000, но затем я сталкиваюсь с переполнением стека. Я не уверен, что JVM откладывает только достаточно памяти для работы до 8 980 или это что-то в моем коде. Я написал разбивку своих условий ниже и вставил код полностью внизу.

public class Numbers {

        private final String HUNDRED = " hundred ";
        private final String THOUSAND = " thousand ";

        private String[] zeroToNineteen = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
        private String[] twentyToOneHundred = { "", "", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" };

Следующий рекурсивный метод - мой единственный метод в моем классе чисел.

   public void toOneMillion(int n) {
            String number = Integer.toString(n);
            String newNumber = "";

Сначала я установил строку number для параметра n с помощью Integer.toString(n).
Затем с каждым условным оператором я вычисляю первое число в последовательности и оттуда использую это число, чтобы задать для String newNumber значение индекса в правильном массиве.

newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))] + THOUSAND;

После этого я печатаю newNumber на консоль, а затем сбрасываю первое число с number и позволяю ему опуститься до следующего условия.

System.out.print(newNumber);
number = number.substring(1, 4);

Затем я повторяю этот шаг до тех пор, пока число не упадет между 0 и 100. Где я затем печатаю номер на консоль и выполняю рекурсивный вызов toOneMillion(n+1); до тех пор, пока n не станет равным 10000 (для целей тестирования).

Полагаю, мой вопрос в том, можно ли достичь от 1 до 1 000 000, не сталкиваясь с переполнением стека? Также, если вы видите в моем коде что-то, чего не должно быть, или код, который может быть написан более эффективным способом (я знаю, что все это может быть написано более эффективным способом, мне просто интересно узнать о более мелких вещах) Вы указываете это и, возможно, объясняете? Большое вам спасибо за чтение этого, и спасибо за любую помощь прийти.

Полный код

У меня есть основной класс, который создает экземпляр класса чисел и вызывает рекурсивный метод через - numbers.toOneMillion(1) ... и это единственный другой класс в папке моего проекта, так что именно этот класс имеет проблему.

public class Numbers {
    private final String HUNDRED = " hundred ";
    private final String THOUSAND = " thousand ";

    private String[] zeroToNineteen = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve",
            "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
    private String[] twentyToOneHundred = { "", "", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" };

    public void toOneMillion(int n) {
        String number = Integer.toString(n);
        String newNumber = "";

        if (n == 10000) {
            System.out.println("10000");
        } else if (n > 0) {
            if (n >= 100) {
                if (n >= 1000) {
                    if (n % 1000 == 0) {
                        newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))] + THOUSAND;
                        System.out.print(newNumber);
                        number = number.substring(1, 4);
                    } else {
                        newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))] + THOUSAND;
                        System.out.print(newNumber);
                        number = number.substring(1, 4);
                        // System.out.println("HELLO!" + number + " " + n);

                    }
                }

                if (Integer.parseInt(number) != 0) {
                    if (n % 100 == 0) {
                        if(zeroToNineteen[Integer.parseInt(number.substring(0, 1))].equals("")) {
                            newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))];
                            System.out.print(newNumber);
                            number = number.substring(1, 3);
                        } else {
                            newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))] + HUNDRED;
                            System.out.print(newNumber);
                            number = number.substring(1, 3);
                        }
                    } else {
                        if(zeroToNineteen[Integer.parseInt(number.substring(0, 1))].equals("")) {
                            newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))] + "and ";
                            System.out.print(newNumber);
                            number = number.substring(1, 3);
                        } else {
                            newNumber = zeroToNineteen[Integer.parseInt(number.substring(0, 1))] + HUNDRED + "and ";
                            System.out.print(newNumber);
                            number = number.substring(1, 3);
                        }
                        // System.out.println("HELLO!" + number + " " + n);

                    }
                }
            }
            if (Integer.parseInt(number) < 20) {
                System.out.println(zeroToNineteen[Integer.parseInt(number)]);
                toOneMillion(n + 1);
            } else {
                if (n % 10 == 0) {
                    number = number.substring(0, 1);
                    newNumber = twentyToOneHundred[Integer.parseInt(number)];
                    System.out.println(newNumber);
                    toOneMillion(n + 1);
                } else {
                    newNumber = twentyToOneHundred[Integer.parseInt(number
                            .substring(0, 1))];
                    newNumber += zeroToNineteen[Integer.parseInt(number
                            .substring(1))];
                    System.out.println(newNumber);
                    toOneMillion(n + 1);
                }
            }
        }
    }
}

Я понимаю, что мой код перемешан, и я должен разбить все мои условные выражения на один метод, который обрабатывает одну и ту же вещь для каждого условного выражения. Я просто хотел бы сначала заставить код работать, а затем усовершенствовать его. Кроме того, я почти уверен, что есть гораздо более эффективный способ сделать то, что я пытаюсь сделать, однако мой мозг и обработка мыслей придумали это, так что не ненавидь усердно.

Ответы [ 2 ]

4 голосов
/ 03 апреля 2012

У меня такое чувство, что вы не понимаете, где они ожидают рекурсию.

Думая больше по линиям:

for(int i=0; i<100000; i++){
   printNumberRecursively(i);
}

Где printNumberRecursively рекурсивно пробегает число по одной цифре за раз.

Если я ошибаюсь, тогдазадание смешно.

1 голос
/ 03 апреля 2012

Не делай toOneMillion(n + 1).Это добавляет информацию в стек при каждом рекурсивном вызове.Вместо этого вы должны вызывать toOneMillion внутри цикла for.

...