Разделить на ноль исключений с Typecaste (Java)

import java.util.Scanner;


public class SumDigits {

public static void main(String[] args)
{
    // TODO Auto-generated method stub

    Scanner input = new Scanner(System.in);

    // prompt the user to enter a value and store it as the integer called number
    System.out.print("Enter an integer: ");
    double number = Math.abs(input.nextDouble());

    System.out.println("The sum of the digits is " + sumNumbers(number));

    input.close();
}
public static int sumNumbers (double number)
{

    int sum = 0;

    for (int i = 10, digit = 0; (number * 10) /i !=0; i *= 10, digit = (int)((number % i) - digit)/(i / 10))
    {
        sum += digit;
    }

    return sum;
}
}

Во время выполнения я получаю сообщение об ошибке

Исключение в потоке "main" java.lang.ArithmeticException: / ноль

ссылаясь на строку 25 (мой для условий цикла).

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

4 ответа

Причина, по которой он терпит неудачу с int а не с double потому что значение переполнено. Если вы отображаете значения i на каждом шаге (начиная с 10) вы можете увидеть следующие значения:

10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
1410065408
1215752192
-727379968
1316134912
276447232
-1530494976
1874919424
1569325056
-1486618624
-1981284352
1661992960
-559939584
-1304428544
-159383552
-1593835520
1241513984
-469762048
-402653184
268435456
-1610612736
1073741824
-2147483648

И тогда это терпит неудачу. Последнее значение, которое он использует, -2147483648, является минимальным значением, которое может быть сохранено в int, Когда вы умножаете его на 10 в следующем проходе цикла, он становится равным 0, который затем используется в делении и вылетает.

Если вы хотите исправить проблему, вам нужно либо изменить свой алгоритм, либо использовать что-то более точное.

Здесь вы делаете

(number * 10) /i !=0

где число двойное

Числа с плавающей запятой не рекомендуются для сравнений из-за того, как они хранятся (в мантиссах и экспонентах). Так что, если это условие вернется, считайте себя счастливчиком.

Из-за этого ваш цикл - своего рода бесконечный цикл. Причина, по которой вы получаете арифметическое исключение, заключается в том, что здесь вы умножаете i на 10 в этом бесконечном цикле. "i" достигает "целочисленного" предела в 32 бита и переполняется и в конечном итоге делает все эти 32 бита равными 0.

Фактически, i=0, и оба следующих броска делятся на исключение нуля

(number * 10) /i 

а также

(number % i) - digit)/(i / 10)

Основной причиной ArithmeticException является неверное условие цикла. Добавление System.out.println("i=" + i + " i*10=" + (i * 10)); в цикле выдает вывод:

i=10 i*10=100
i=100 i*10=1000
i=1000 i*10=10000
i=10000 i*10=100000
i=100000 i*10=1000000
i=1000000 i*10=10000000
i=10000000 i*10=100000000
i=100000000 i*10=1000000000
i=1000000000 i*10=1410065408
i=1410065408 i*10=1215752192
i=1215752192 i*10=-727379968
i=-727379968 i*10=1316134912
i=1316134912 i*10=276447232
i=276447232 i*10=-1530494976
i=-1530494976 i*10=1874919424
i=1874919424 i*10=1569325056
i=1569325056 i*10=-1486618624
i=-1486618624 i*10=-1981284352
i=-1981284352 i*10=1661992960
i=1661992960 i*10=-559939584
i=-559939584 i*10=-1304428544
i=-1304428544 i*10=-159383552
i=-159383552 i*10=-1593835520
i=-1593835520 i*10=1241513984
i=1241513984 i*10=-469762048
i=-469762048 i*10=-402653184
i=-402653184 i*10=268435456
i=268435456 i*10=-1610612736
i=-1610612736 i*10=1073741824
i=1073741824 i*10=-2147483648
i=-2147483648 i*10=0

Первый раз контроль вводит в цикл значение digit будет ноль, а не последняя цифра введенного числа, как вы ожидали. Также вам нужно исправить условие завершения цикла, так как это неправильно. Например, если число равно 123, то на последней ожидаемой итерации 1230/1000 = 1 и не 0 и цикл не заканчивается и скорее приводит к переполнению. Вы можете использовать следующее:

public static int sumNumbers (double number)
    {
        int sum = 0;
        for (int i = 10, digit = (int)(number % i); digit != 0; i *= 10, digit = (int)((number % i) - digit)/(i / 10))
        {
            sum += digit;
        }

        return sum;
    }

Это должно работать, но я снова рекомендую вам улучшить этот код, так как это не идеальный способ.

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

Enter an integer: 3456 The sum of the digits is 18

Другие вопросы по тегам