2010-05-14 18 views
10

Para un proyecto pequeño (Problema 10 Proyecto Euler) intenté resumir todos los números primos por debajo de 2 millones. Así que utilicé un método de fuerza bruta y repetí de 0 a 2'000'000 y verifiqué si el número es primo. Si es que he añadido a la suma:¿Por qué Java no me dice cuándo no puedo usar Integer?

private int sum = 0; 

private void calculate() { 
    for (int i = 0; i < 2000000; i++) { 
     if (i.isPrime()) { 
     sum = sum + i; 
     } 
    } 
    sysout(sum) 
} 

El resultado de este cálculo es 1179908154, pero esto es incorrecto. Así que cambié int a BigInteger y ahora obtengo la suma correcta 142913828922. Obviamente, el rango de int se desbordó. Pero ¿por qué Java no puede decirme eso? (por ejemplo, por una excepción)

+3

Como acotación al margen, BigInteger es un exceso y largo habría funcionado bien. – DJClayworth

+0

¿Por qué no usas Tamiz de Eratóstenes en lugar de fuerza bruta? – CoolBeans

+1

@DJClayworth: intentaré @CoolBeans: la fuerza bruta es lo suficientemente rápida, solo toma una fracción de segundo – RoflcoptrException

Respuesta

13

Porque es posible que desee que se comporte de la manera Integer tradicional. Las excepciones están reservadas para cosas que definitivamente y irrevocablemente están equivocadas.

ETA: A partir de la especificación de lenguaje:

"Los operadores enteros incorporadas no hacen indican desbordamiento positivo o negativo de ninguna manera Los únicos operadores numéricos que puede lanzar una excepción (art. 11) son el operador de división de enteros/(§15.17.2) y el operador de resto entero% (§15.17.3), que arroja una ArithmeticException si el operando de la derecha es cero. "

(http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html)

+0

entonces siempre debo probar antes de agregar un número si se excede el rango? – RoflcoptrException

+4

Si sabes que tu número puede ser grande, debes usar una clase 'más grande' para manejarlo. –

+0

Estoy de acuerdo con Felipe. Si necesita una garantía que x + 1> x para valores por encima del rango del Integer, use BigInteger. Si está utilizando un int por otro motivo, Integer debería estar bien. –

3

Además de lo que dice Jim, la comprobación de las condiciones tales como desbordamiento añadiría una penalización de rendimiento a cualquier cálculo realizado con enteros, lo que haría que los programas que hacen un montón de cálculos mucho más lento.

+2

y _esta_ es la verdadera razón por la que se hace de esa manera. ¡También es por eso que tenemos primitivos! – naiad

+0

@Vuntic No creo que esa sea la verdadera razón por la que tenemos primitivos: en otros lenguajes (por ejemplo, Scala), el compilador es lo suficientemente inteligente como para utilizar enteros nativos cuando utiliza, por ejemplo, la clase Int. En otras palabras, si el compilador de Java se hubiera hecho más inteligente, los tipos de datos primitivos no tendrían que haber estado expuestos en el lenguaje de programación. – Jesper

+0

1) Estás comparando 2 idiomas cuyos orígenes tienen más de 15 años de diferencia. 2) Un compilador Java no puede ser "inteligente" y reemplazar un tipo con otro ... a menos que el JLS lo sancione. (Las reglas para la asignación definitiva son otro ejemplo en el que el compilador de Java no puede ser "inteligente"). –

0

Consciente de Integer.MAX_VALUE es siempre útil :)

1

La otra razón es que se puede hacer esto compruebe usted mismo muy fácilmente y rápidamente.

if (sum+i < sum) { 
    throw new AritchmeticException(); 
} 

debe hacer el truco muy bien, teniendo en cuenta que usted sabe que es siempre positivo y menos de Integer.MAX_VALUE.

0

Porque nuestra profesión valora el rendimiento sobre la corrección. ;. (

Usando BigInteger por defecto, y sólo el razonamiento si es aceptable, para usar largo o int si el rendimiento es un problema real, ayudaría a evitar este tipo de problemas

+0

En realidad, los diseñadores del lenguaje Java quieren dar a los programadores la opción de valorar el rendimiento por encima de la corrección. – DJClayworth

Cuestiones relacionadas