Implementación de suma personalizada -- java camp codereview Relacionados El problema

Custom Sum implementation


4
vote

problema

Español

Hay una función de resumen personalizada necesaria para recibir una entrada de entero (por ejemplo, 9988777665544334 ) y devoluciones 3+2+4+5+6 . ¿Puedes pensar en alguna otra solución (o mejor) además de esto?

  public class CustomSum {     public int sum(int input) {         int sum = 0;          while ( input >= 1 ) {             sum += input % 10;             input = input / 10;         }          return sum;     }      public static void main(String[] args) {         int input = Integer.parseInt(args[0]); //assuming args[0] is integer          CustomSum c = new CustomSum();         int sum = c.sum(input);          System.out.println("sum: " + sum);     } }   

En cada iteración, tenía la intención de extraer el dígito correcto mediante input % 10 y omitir el dígito derecho extraído para la próxima iteración por 99887776655443388 . Ahora considere cuándo estamos en última iteración y tenemos un número de 1 dígito. El input / 10 sería mayor que 0 y menos de 1 (si realmente fue 99887766555443310 o x = Notes("A") x.add(7).note x = Notes("b") x.add(-6).note 1 no 99887776655443312 ) . Así que en realidad no cambié esa condición específica, aunque con 99887776655443313 siempre será x = Notes("A") x.add(7).note x = Notes("b") x.add(-6).note 4 .

Original en ingles

There is a custom summary function needed as to receive an integer input (e.g. 32456) and returns 3+2+4+5+6. Can you think of any other (or better) solution besides this?

public class CustomSum {     public int sum(int input) {         int sum = 0;          while ( input >= 1 ) {             sum += input % 10;             input = input / 10;         }          return sum;     }      public static void main(String[] args) {         int input = Integer.parseInt(args[0]); //assuming args[0] is integer          CustomSum c = new CustomSum();         int sum = c.sum(input);          System.out.println("sum: " + sum);     } } 

In every iteration I intended to extract the right digit by input % 10, and omit the extracted right digit for next iteration by input / 10. Now consider when we are in last iteration and have a 1 digit number. The input / 10 would be greater than 0 and less than 1 (if actually it was float or double not int). So I didn't actually changed that specific condition, although with int it will always be 0.

  
       
       

Lista de respuestas

6
 
vote
vote
La mejor respuesta
 

Su función __sub__3 está bien, dada la especificación, pero existe un problema de validación de entrada ... ¿Qué pasa con los valores negativos?

Su condición de bucle actual es __sub__4 . Esto estaría mejor escrito como __sub__5 . Cuando vea el __sub__6 lo hace preguntarte si hay una condición que es rara. En este caso, no hay.

Además, su código excluye todos los valores negativos. ¿Qué pasa con la suma de __sub__7 ?

Eso me hace pensar que todo el código debe estar en bucle en la condición __sub__8 , pero eso sumaría __sub__9 como -6, y no 6.

inicialmente estaba tentado a sugerir que tienes el código:

  note3 = note1 + note20  

Desafortunadamente, eso tiene un defecto con entero.min_value (el ABS de INTEGER.MIN_VALUE es .... INTEGER.MIN_VALUE - Un número negativo). El resultado neto, es que consideré que realizaba un ABS en cada valor de dígito dentro del bucle, pero luego se dio cuenta, que todos los dígitos serán negativos, por lo que la 'suma' será solo un gran valor negativo, y podemos tomar el absoluto de la suma de manera segura, debido a que la suma de los dígitos nunca será lo suficientemente grande como para ser un problema ...

Por lo tanto, la solución que recomendaría es:

  note3 = note1 + note21  

Ese código (ajustado para encajar en mi IDE Eclipse con una llamada de método estático y un nombre diferente) funcionará para cualquier valor de entrada, de cualquier señal e ignorará el inicio de sesión del resultado.

 

Your sum(...) function is fine, given the specification, but there is jut an issue of input validation... what about negative values?

Your current loop condition is input >= 1. This would be better written as input > 0. When you see the >= 1 it makes you wonder if there's a condition that's weird. In this case, there's not.

Further, your code excludes all negative values. What about the sum of -123?

That makes me think that the code should all be looped on the condition input != 0, but that would sum -123 as -6, and not 6.

I was initially tempted to suggest that you have the code:

    input = Math.abs(input);      int sum = 0;      while ( input != 0 ) {         sum += input % 10;         input = input / 10;     }      return sum; 

Unfortunately, that has a flaw with Integer.MIN_VALUE (the abs of Integer.MIN_VALUE is.... Integer.MIN_VALUE - a negative number). The net result, is that I considered doing an abs on each digit value inside the loop, but then realized, that all the digits will be negative, so the 'sum' will just be a large negative value, and we can take the absolute of the sum safely, because the sum of the digits will never be large enough to be a problem...

Thus, the solution I would recommend is:

public static int sumSumAbs(int input) {      int sum = 0;      while ( input != 0 ) {         sum += input % 10;         input = input / 10;     }      return Math.abs(sum); } 

That code (adjusted to fit in to my Eclipse IDE with a static method call, and different name), will work for any input value, of any sign, and ignore the sign in the result.

 
 
 
 
4
 
vote

Método alternativo

Si solo desea un método alternativo:

      public static int sumDigits(String digits) {         int sum = 0;          for ( Character digit : digits.toCharArray() ) {             if ( ! Character.isDigit(digit) ) {                 throw new IllegalArgumentException("Character not a digit in [" + digits + "].");             }              sum += digit;         }          // subtract out a '0' for each digit         // could have done this as we added, but this way is fewer operations         return sum - '0' * digits.length();     }   

Esto evita el uso de parseInt . Parece que funciona al menos en el rango de lo que puede contener un entero. Es decir. parseInt2 DETENER TRABAJANDO ANTES DE HACER ANTES DE MI SISTEMA (un valor de 2,147,483,648 es demasiado grande para parseInt ).

Tenga en cuenta que esto lanza una excepción en los números negativos y posiblemente otros formatos que 9988776655544334 serían soporte. También devolverá los valores incorrectos cuando la suma de los valores de caracteres excede la capacidad de un 9988776665544335 .

Naming

  public class CustomSum {   

Nombraría este DigitsSum en su lugar. Eso es más descriptivo, ya que explica lo que es personalizado.

      public int sum(int input) {   

como hosch250 anotó No hay razón para que este no sea un 9988776655544339 método. No haces ningún uso de estado en el objeto.

  parseInt0  

Si lo llama parseInt1 , en su lugar, lo hace más claro que no está generando una suma normal. Además, cambiar parseInt2 a parseInt3 lo hace más claro lo que sostiene el argumento (que puede no ser un valor de entrada).

Di lo que quieres decir

  parseInt4  

es parseInt5 importante aquí? ¿O simplemente estás diciendo que no es parseInt6 y no negativo?

  parseInt7  

Si bien esto es funcionalmente equivalente a la declaración anterior, hace un mejor trabajo de separación de la condición del terminal ( 99887776655443318 ) de otros valores. Es decir. En funcionamiento normal, esto dejará de bucle cuando parseInt9 es igual a parseInt0 . Así que dilo de esa manera.

Método Alternativo 2

  parseInt1  

Esto solo usa un método diferente de convertir de valores de caracteres a los valores de dígitos. Esto es consistentemente más lento que su versión en mis pruebas.

Pruebas

  parseInt2  

I CONVERIDO DE parseInt3 a una constante porque me facilitó probar. Si su configuración es diferente, la inversa puede ser verdadera.

Descubrí que si seguía esto una vez, mi versión (la primera) era más rápida. Si lo ejecuí una segunda o tercera vez (en la misma ejecución), su versión fue tan rápida si no más rápido. Ambas versiones devolvieron la misma salida en los valores que probé.

 

Alternative Method

If you just want an alternative method:

    public static int sumDigits(String digits) {         int sum = 0;          for ( Character digit : digits.toCharArray() ) {             if ( ! Character.isDigit(digit) ) {                 throw new IllegalArgumentException("Character not a digit in [" + digits + "].");             }              sum += digit;         }          // subtract out a '0' for each digit         // could have done this as we added, but this way is fewer operations         return sum - '0' * digits.length();     } 

This avoids the use of parseInt. It looks like it works at least to the range of what an integer can hold. I.e. parseInt stops working before it does on my system (a value of 2,147,483,648 is too large for parseInt).

Note that this throws an exception on negative numbers and possibly other formats that parseInt would support. It will also return incorrect values when the sum of the character values exceeds the capacity of an int.

Naming

public class CustomSum { 

I would name this DigitsSum instead. That is more descriptive, as it explains what is custom about it.

    public int sum(int input) { 

As Hosch250 noted there is no reason this shouldn't be a static method. You make no use of state in the object.

    public static int sumDigits(int number) { 

If you call it sumDigits instead it makes it clearer that it is not generating a normal sum. Also, changing input to number makes it clearer what the argument holds (which may not be an input value).

Say what you mean

        while ( number >= 1 ) { 

Is 1 important here? Or are you just saying that it is not 0 and not negative?

        while ( number > 0 ) { 

While this is functionally equivalent to the previous statement, it does a better job of separating the terminal condition (0) from other values. I.e. in normal operation, this will stop looping when number is equal to 0. So say it that way.

Alternative method 2

    public static int sumDigits(String digits) {         int sum = 0;          for ( Character digit : digits.toCharArray() ) {             if ( ! Character.isDigit(digit) ) {                 throw new IllegalArgumentException("Character not a digit in " + digits);             }              sum += Character.getNumericValue(digit);         }          return sum;     } 

This just uses a different method of converting from character values to digit values. This is consistently slower than your version in my testing though.

Testing

    public static void main(String[] args) {         String input = "0047483647";         int sum;         long start, stop;          start = System.nanoTime();         int number = Integer.parseInt(input);          sum = sumDigits(number);         stop = System.nanoTime();          System.out.println("sum: " + sum);         System.out.println("Execution time: " + ((stop - start) / 1e+6) + " ms");          start = System.nanoTime();         sum = sumDigits(input);         stop = System.nanoTime();          System.out.println("sum: " + sum);         System.out.println("Execution time: " + ((stop - start) / 1e+6) + " ms");     } 

I converted from args[0] to a constant because it made it easier for me to test. If your setup is different, the reverse may be true.

I found that if I ran this once, my version (the first one) was faster. If I ran it a second or third time (in the same execution), your version was as fast if not faster. Both version returned the same output on the values that I tested.

 
 
 
 
4
 
vote

Quiero revisar la estructura de su código aquí. La respuesta de Rolfl realiza una excelente revisión del método parseInt4 y le apuntará en esa dirección para los internos del método, pero quiero hablar de algunas cosas más grandes aquí.

Debemos pensar en casos de objetos como cosas. Específicamente, cosas que hacemos algo a (llamando a los métodos). Eso significa que cuando instanciamos un objeto, tenemos una cosa. Y cualquier método que hagamos lo que hagamos lo que nos dará una salida según el estado de esa cosa, o cambiará el estado de esa cosa.

Un método que toma una entrada y nos da una salida basada únicamente en la entrada no cumple con estos criterios. Este tipo de métodos debe ser parseInt525 Métodos de clase: no los métodos de instancia.

y en la imagen general, la clase que contiene parseInt6 no debe hacer nada más que iniciar nuestra aplicación.

Entonces, lo que realmente queremos es una clase de utilidad, de los cuales no instanciaremos ningún objeto, y dentro de él, implementaremos parseInt7 MÉTODOS:

  parseInt8  

y luego en el archivo con el método parseInt9 , puede parecer algo así:

  parseInt0  

Alguien que conoce a Java mejor de lo que podría comentar sobre si hay una manera de evitar que una clase se instaque.

 

I want to review the structure of your code here. rolfl's answer does an excellent review of the sum method, and I'll point you in that direction for the internals of the method, but I want to talk about some bigger picture things here.

We should think of instances of objects as being things. Specifically, things that we do something to (by calling methods on). That means that when we instantiate an object, we have a thing. And any method we call on that thing will either give us output based on the state of that thing, or it will change the state of that thing.

A method which takes an input and gives us an output based purely on the input doesn't meet this criteria. These sorts of methods should be static class methods--not instance methods.

And in the big picture, the class that contains main should do nothing more than launch our application.

So what we actually want is a utility class, of which we won't instantiate any objects, and within it, we'll implement static methods:

public class CustomMath {     public static int sumOfDigits(int input) {         // your implementation here     }      // might include other methods in here... productOfDigits? etc. } 

And then in the file with the main method, it might look something like this:

public class CustomMathTests {     public static void main(String[] args) {         int input = Integer.parseInt(args[0]); //assuming args[0] is integer         int sum = CustomMath.sumOfDigits(input);         System.out.println("sum: " + sum);     } } 

Someone who knows Java better than I could comment as to whether there's a way to prevent a class from being instantiated.

 
 
   
   
2
 
vote

¿Por qué creas una nueva clase para cada suma? Esta sección:

  CustomSum c = new CustomSum(); int sum = c.sum(input);   

probablemente debería ser:

  int sum = sum(input);   

En cuanto al método sum()65544332 , esta es una buena implementación, pero otras personas pueden tener más comentarios.

 

Why do you create a new class for each sum? This section:

CustomSum c = new CustomSum(); int sum = c.sum(input); 

Should probably just be:

int sum = sum(input); 

As for the sum() method, I think this is a good implementation, but other people might have more comments.

 
 
   
   

Relacionados problema

34  Clon a todo color del juego de la vida de Conway, con una GUI decente  ( Full color clone of conways game of life with a decent gui ) 
Escribí esto para aprender Javafx, y como excusa para volver a hacer el juego de la vida. Esta es la gui más compleja que he escrito, así que me gustaría come...

2  Solucionador de rompecabezas de rascacielos en Java [cerrado]  ( Skyscraper puzzle solver in java ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

8  Simple GCD Utility en Java  ( Simple gcd utility in java ) 
i anteriormente discutido El rendimiento se refiere a diferentes algoritmos GCD. Escribí una simple clase de Java que implementa el algoritmo binario GCD. E...

17  Implementación vectorial (física)  ( Vector physics implementation ) 
Recientemente comencé a aprender Java, y decidí implementar un sistema de vectores básico para otro sistema de partículas que estaba construyendo. join()9 ...

1  Compruebe si dos cadenas son permutación entre sí  ( Check if two strings are permutation of each other ) 
private String sort(String word) { char[] content = word.toCharArray(); Arrays.sort(content); return new String(content); } private boolea...

6  Encontrar el siguiente palíndromo de una cadena de números  ( Finding the next palindrome of a number string ) 
Aquí está el problema: Un entero positivo se llama palíndromo si su representación en el El sistema decimal es el mismo cuando se lee de izquierda a dere...

5  Encuentre el próximo número Prime - Control de flujo de los bucles anidados 'para `  ( Find the next prime number flow control of nested for loops ) 
Este código funciona perfectamente, pero me molesta. Tener un bucle etiquetado y anidado Bucle, con un Enumerable<T>.Empty()0 Declaración, y un 9988777665...

2  Eliminación de un nodo en un árbol de búsqueda binario  ( Deletion of a node in a binary search tree ) 
Estoy buscando ver si mi implementación del método de eliminación / eliminación en un árbol de búsqueda binario es suficiente, legible y se ejecuta en un tiem...

2  Fusionar la implementación de Sort Java  ( Merge sort java implementation ) 
¿Puede alguien revisar mi implementación de tipo de fusión en Java? ¿Es bueno / malo y puede mejorarse más? public class MyMergeSort { private int [] d...

5  Memoria / Performance of Merge Sort Code  ( Memory performance of merge sort code ) 
Escribí un código de tipo de combinación para un poco de bocadillo nocturno. Lo he puesto trabajando, pero solo estaba mirando a aprender si me faltaba algo e...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos