2011-01-13 32 views
63

estaba escribiendo este código:¿Por qué es el resultado de 1/3 == 0?

public static void main(String[] args) { 
    double g = 1/3; 
    System.out.printf("%.2f", g); 
} 

El resultado es 0. ¿Por qué es esto y cómo puedo solucionar este problema?

Respuesta

88

Los dos operandos (1 y 3) son enteros, por lo tanto, se utiliza la aritmética entera (división aquí). Declarar la variable de resultado como doble solo causa una conversión implícita que ocurre después de la división.

La división entera del curso devuelve el resultado verdadero de la división redondeada hacia cero. El resultado de 0.333... se redondea aquí a 0. (Tenga en cuenta que el procesador no hace ningún redondeo, pero puede pensarlo de esa manera).

Además, tenga en cuenta que si ambos operandos (números) se dan como flotantes; 3.0 y 1.0, o incluso solo el primero, luego se usa la aritmética de coma flotante, que le da 0.333....

+19

+1 y siempre redondea hacia abajo. 'int i = .99999999' establece int en 0. Más específicamente, toma la parte entera y descarta el resto. –

+24

Redondea "hacia cero", que es "hacia abajo" para valores superiores a cero. (+0.9 se redondea a 0, -0.9 también se redondea a 0.) –

+0

@Byron: Sí, exactamente. No creo que el procesador realmente redondee, ya que la división se implementa de manera muy diferente, pero es útil pensarlo de esa manera. – Noldorin

7

convierta explícitamente como un double

double g = 1.0/3.0 

Esto sucede porque Java utiliza la operación de la división entera de 1 y 3 ya se han introducido como constantes enteras.

0

1 y 3 son contajes enteros, por lo que Java hace una división entera cuyo resultado es 0. Si desea escribir constantes dobles, debe escribir 1.0 y 3.0.

-1

Do "doble g = 1.0/3.0;" en lugar.

+0

Simplemente curioso ... ¿Qué pasa con esta respuesta? Usé este enfoque cuando encontré el problema por primera vez. Una explicación de lo que está mal con esta solución sería apreciada. Gracias por adelantado. –

1

Porque estás haciendo una división entera.

Como dice @Noldorin, si ambos operadores son enteros, entonces se usa la división de enteros.

El resultado 0.33333333 no se puede representar como un entero, por lo tanto, solo se asigna la parte entera (0) al resultado.

Si cualquiera de los operadores es double/float, se realizará una aritmética de coma flotante. Pero vas a tener el mismo problema si se hace eso:

int n = 1.0/3.0; 
1

porque trata a 1 y 3 como números enteros, por lo tanto, redondeando el resultado a 0, por lo que es un entero.

Para obtener el resultado que busca, dicen explícitamente java que los números son dobles, así:

double g = 1.0/3.0; 
-1

hacer que el 1 un flotador y flotador de la división se utilizarán

public static void main(String d[]){ 
    double g=1f/3; 
    System.out.printf("%.2f",g); 
} 
12

1/3 usa la división de enteros ya que ambos lados son enteros.

Necesita al menos uno de ellos para ser float o double.

Si está ingresando los valores en el código fuente como su pregunta, puede hacer 1.0/3; el 1.0 es un doble.

Si obtiene los valores de otra parte, puede usar (double) para convertir el int en double.

int x = ...; 
int y = ...; 
double value = ((double) x)/y; 
2

se debe utilizar

double g=1.0/3; 

o

double g=1/3.0; 

La división entera vuelve entero.

0

Muchos otros han dejado de señalar el verdadero problema:

Una operación en sólo enteros arroja el resultado de la operación a un entero.

Esto necesariamente significa que los resultados de punto flotante, que podría se mostrará como un entero, se truncarán (lop de la parte decimal).

¿Qué es fundición (conversión de tipografía/tipo) preguntas?

Varía en la implementación del idioma, pero Wikipedia tiene una visión bastante completa, y también habla de coerción, que es una pieza fundamental de información al responder a su pregunta.

http://en.wikipedia.org/wiki/Type_conversion

1

La conversión en Java es bastante simple, pero necesita un poco de comprensión. Como explicar en el JLS para integer operations:

Si un operador entero distinto de un operador de desplazamiento ha al menos un operando de tipo largo, entonces la operación se lleva a cabo utilizando precisión de 64 bits, y el resultado de la numérico el operador es de tipo largo. Si el otro operando no es largo, primero se amplía (§5.1.5) para escribir largo por promoción numérica (§5.6).

Y un ejemplo es siempre la mejor manera de traducir el JLS;)

int + long -> long 
int(1) + long(2) + int(3) -> long(1+2) + long(3) 

De lo contrario, la operación se lleva a cabo utilizando una precisión de 32 bits, y el resultado del operador numérico es de tipo int. Si ninguno de los operandos es un int, primero se amplía para escribir int por promoción numérica.

short + int -> int + int -> int 

Un pequeño ejemplo usando Eclipse para mostrar que incluso una adición de dos short s no será tan fácil:

short s = 1; 
s = s + s; <- Compiling error 

//possible loss of precision 
// required: short 
// found: int 

Esta voluntad necesaria una pieza de fundición con una posible pérdida de precisión.

Lo mismo es cierto para el floating point operators

Si al menos uno de los operandos a un operador numérico es de tipo doble, a continuación, la operación se llevó a cabo utilizando la aritmética de coma flotante de 64 bits, y el El resultado del operador numérico es un valor de tipo double. Si el otro operando no es un doble, primero se amplía (§5.1.5) para escribir double por promoción numérica (§5.6).

Así que la promoción se realiza en el flotador en el doble.

Y la mezcla de ambos número entero y el resultado valor flotante en valores flotante como se ha dicho

Si al menos uno de los operandos a un operador binario es de tipo de punto flotante, a continuación, la operación es un flotante operación puntual, incluso si la otra es integral.

Esto es cierto para los operadores binarios, pero no para "Operadores de asignación" como +=

Un simple ejemplo de trabajo es suficiente para probar este

int i = 1; 
i += 1.5f; 

La razón es que hay una conversión implícita hecho aquí, esto se ejecutará como

i = (int) i + 1.5f 
i = (int) 2.5f 
i = 2 
-1

(1/3) significa entero divisio n, es por eso que no puede obtener el valor decimal de esta división. Para resolver este problema use:

public static void main(String[] args) { 
     double g = 1.0/3; 
     System.out.printf("%.2f", g); 
    } 
Cuestiones relacionadas