最快的方法是提取每个数字并随时添加。
public static void main(String... args) {
// check values
int runs = 1000000;
for (int i = 100; i < runs; i++) {
int sum = sumDigits(i - 1);
int sum1 = sumDigits(i);
int sum2 = sumDigits(sum, i);
if (sum1 != sum2) throw new AssertionError(i + ": " + sum1 + " != " + sum2);
}
long start = System.nanoTime();
for (int i = 0; i < runs; i++) {
int sum = sumDigits(i);
// prevent optimising away.
if (sum < 0) throw new AssertionError();
}
long time = System.nanoTime() - start;
System.out.printf("sumDigits took an average of %,d ns%n", time / runs);
long start2 = System.nanoTime();
int lastSum = 0;
for (int i = 0; i < runs; i++) {
int sum = sumDigits(lastSum, i);
lastSum = sum;
// prevent optimising away.
if (sum < 0) throw new AssertionError();
}
long time2 = System.nanoTime() - start2;
System.out.printf("sumDigits using previous value took an average of %,d ns%n", time2 / runs);
long large = Long.MAX_VALUE - runs - 1;
long start3 = System.nanoTime();
for (int i = 0; i < runs; i++) {
int sum = sumDigits(large + i);
// prevent optimising away.
if (sum < 0) throw new AssertionError();
}
long time3 = System.nanoTime() - start3;
System.out.printf("sumDigits took an average of %,d ns%n", time3 / runs);
long start4 = System.nanoTime();
int lastSum2 = sumDigits(large);
for (int i = 0; i < runs; i++) {
int sum = sumDigits(lastSum2, large + i);
lastSum2 = sum;
// prevent optimising away.
if (sum < 0) throw new AssertionError();
}
long time4 = System.nanoTime() - start4;
System.out.printf("sumDigits using previous value took an average of %,d ns%n", time4 / runs);
}
public static int sumDigits(long n) {
int sum = 0;
do {
sum += n % 10;
n /= 10;
} while (n > 0);
return sum;
}
public static int sumDigits(int prevSum, long n) {
while (n > 0 && n % 10 == 0) {
prevSum -= 9;
n /= 10;
}
return prevSum + 1;
}
印刷
sumDigits took an average of 32 ns
sumDigits using previous value took an average of 10 ns
sumDigits took an average of 79 ns
sumDigits using previous value took an average of 7 ns
对于较大的值,它可以节省大约 70 ns。它给你的代码增加了一些复杂性。您必须使用第一个 sumDigit 来引导总和,因为您无法从 1 一直数到 10^18。