What is the most performative way of converting an int to the sum of its digits?

4

I have a certain int and would like to turn it into another one that is the result of summing your digits in the best possible way. For example:

int n = 2601;

Should result in 9 since this is the result of 2+6+0+1 . What is the best way to get this behavior?

Based on this Stack Overflow answer I will list two ways, but I have not thought of a way to test which one performs better and I do not know if there is any other possibility that stands out to these too:

Form 1:

public int somarDigitos(int numero) {
  int resultado = 0;

  while (numero != 0) {
    int digito = numero % 10;
    numero = numero / 10;
    resultado = resultado + digito;
  }

  return resultado;
}

Form 2:

public int somarDigitos2(int numero) {
  String texto = String.valueOf(numero);
  int resultado = 0;

  for (char digito : texto.toCharArray()) {
    resultado = resultado + Character.getNumericValue(digito);
  }

  return resultado;
}
    
asked by anonymous 27.11.2017 / 05:50

1 answer

3

The best way to know which one is faster is to do tests running the expected algorithm many times and compare.

Of course the test needs care not to give biased results. I answered something towards C # , but almost anything goes for Java.

Number manipulation is a native processor operation and has high performance.

The algorithm with number will do 3 math operations, at most 3 data transports (it is likely that some optimization will hold something in the register and get much faster and will have a branch , which can plus bring delay, but I think the prediction of processor drift should work fine in this case.

I'll discard the load I need to convert string to array from char , assuming the language does some optimization and does not have to do anything heavy, but if you really have to do physical work here you must already have a performance commitment. The question does not want to know details:)

It has at least one brach of for , perhaps more because what I saw of getNumericValue() does checks on the merits of the content. At the very least it has a mathematical operation and a transport within the function. If you can not linearize the function it gets much worse because you will not be able to optimize for registrar use, there will be 2 more transports and more overhead to manage the function call .

It has a mathematical operation and a visible transport in code. But a lot of things invisible. And it seems that this part is much heavier than it looks.

I took a test and the difference is two orders of magnitude. But it can vary in certain circumstances. I expect a good difference, but not that big, so testing is important.

I tested the algorithm, because even knowing the difference in performance is what should be analyzed.

I tested in different environments and the results were consistent.

But in actual use has a series and other things to solve. And it seems to me that Java is not good at optimizing this. If you call a function with the algorithm the function call will weigh heavily and puts the two algorithms closer to par.

If I do not have something I do not know how to do in Java it makes a lot of difference to call a function or execute directly. It is there for the Javeiros with wide experience in this to speak. I admit that I may have been wrong in the assessment, but not easy to understand.

class HelloWorld {
    public static void main(String []args) {
        int numero = 123456;
        long time = System.nanoTime();
        for (int i = 0; i < 10000000; i++) {
            int resultado = 0;
            while (numero != 0) {
                numero /= 10;
                resultado += numero % 10;
            }
        }
        System.out.println((System.nanoTime() - time) + "ns");
        time = System.nanoTime();
        for (int i = 0; i < 10000000; i++) {
            String texto = String.valueOf(numero);
            int resultado = 0;
            for (char digito : texto.toCharArray()) {
                resultado = resultado + Character.getNumericValue(digito);
            }
        }
        System.out.println((System.nanoTime() - time) + "ns");
    }
}

See running on ideone . And at Coding Ground . Also put it in GitHub for future reference .

    
27.11.2017 / 12:13