2013-08-25 1 views
1

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

Например, 111111111111L Хотелось бы связаться с нами 12L.

Как достичь такого же ожидаемого поведения, описанного в следующем вопросе (который работает только для значений типа int)? Sum of all digits for a given Positive Number

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

public static long sumTheDigitsVersion1(long inputValue){ 
    long sum = inputValue % 9L; 
     if(sum == 0){ 
      if(inputValue > 0) 
       return 9L; 
     } 
    return sum; 
} 

public static long sumTheDigitsVersion2(long inputValue){ 
    return inputValue - 9L * ((inputValue - 1L)/9L); 
} 

Благодаря

+0

Не надейтесь на ресурсы вне участка в своем запросе. Свяжите их, если хотите, но всегда указывайте соответствующие бит в своем вопросе. –

+0

Почему вы ожидаете '12' в качестве вывода. Этот вопрос, который вы связали, обнаружил ['цифровой корень'] (http://en.wikipedia.org/wiki/Digital_root), который уменьшает число, суммируя цифры, пока вы не получите одну цифру. Таким образом, для '12' он снова будет уменьшен до' 1 + 2 = 3'. –

+0

@dasblinkenlight. '111111111111L' можно считать десятичным? –

ответ

1

Я получил следующее решение после нескольких тестов с другим номером ы сравнения 3 различных функций, связанных с 3-х различных подходов:

  • toCharArray() и петли,
  • основные математические вычисления и циклы,
  • рекурсию.

Я сравнил 3 разных подхода в соответствии с их временным измерением, используя System.nanoTime().

public static long sumTheDigits(long currentIterationValue){ 

    long currentDigitValue; 
    long sumOutputValue = 0; 

    while(currentIterationValue != 0) { 
     currentDigitValue = currentIterationValue % 10; 
     currentIterationValue = currentIterationValue/10; 
     sumOutputValue = sumOutputValue + currentDigitValue; 
    } 
    return sumOutputValue; 
} 
3

Решение не работает, потому что это решение другой проблемы, а именно:

неоднократно сложить цифры числа, пока вы не достичь результата одной цифры ,

Другими словами, он вычисляет 111111111111 ->12 ->3.

Если вы думаете об этом, n % 9 не может вернуть 12 (это то, что вы говорите, что ожидаете).

+0

Хорошо, я запутался в двух разных проблемах, спасибо, что выделил его. Теперь я все еще пытаюсь понять, что является наиболее эффективным способом решения проблемы, например, с учетом этого ввода '111111111111' Я хотел бы получить сумму своих цифр, т. Е.' 12'. – TPPZ

1

Это не может быть наиболее эффективным вариантом Буц его только один я могу думать на верхней части моей головы:

public static long getDigitalSum(long n){ 
    n = Math.abs(n); //This is optional, remove if numbers are always positive. NOTE: Does not filter Long.MIN_VALUE 

    char[] nums = String.valueOf(n).toCharArray(); 
    long sum = 0; 

    for(char i:nums){ 
     sum = sum + Integer.parseInt(String.valueOf(i)); //Can use Long.parseLong() too 
    } 

    return sum; 
} 
+0

Обратите внимание, что 'Math.abs (n) == n' для' n = Long.MIN_VALUE'. Лучше пропустить символ '-' или просто отклонить отрицательный ввод с помощью' IllegalArgumentException'. – Boann

+0

@ Бонн Окей ... Я этого не знал. Я думал, так как он хотел быть эффективным, выполнение if-заявления для персонажа, вероятно, было бы очень плохо. Спасибо за информацию! – initramfs

+0

Это в любом случае наименее эффективное решение, так что ... – Boann

2

рекуррентных, эффективное решение:

public static long digitSum(long n) { 
    if (n == 0) 
     return 0; 
    return n%10 + digitSum(n/10); 
} 
+1

Эффективно, если JVM может превратить его в цикл, который, вероятно, не может. – Boann

2

О качестве эффективной как вы его получите:

private static final int PART_SIZE = 1000; 
private static final int[] digitSums = new int[PART_SIZE]; 
static { 
    for (int i = 0; i < digitSums.length; i++) { 
     for (int n = i; n != 0; n /= 10) digitSums[i] += n % 10; 
    } 
} 

public static long digitSum(long n) { 
    int sum = 0; 
    do { 
     sum += digitSums[(int)(n % PART_SIZE)]; 
    } while ((n /= PART_SIZE) != 0); 
    return sum; 
}