2010-10-20 19 views
33

Tengo el siguiente bucle:bytes sin fin inesperado para un bucle

for (byte i = 0 ; i < 128; i++) { 
    System.out.println(i + 1 + " " + name); 
} 

Cuando ejecuto mi programm se imprime todos los números de -128 a 127 en un bucle infinito. ¿Por qué pasó esto?

+0

¿Qué quieres decir con que 'parece ser interminable'? – Fermin

+3

@Suresh S: Usted escribió "el byte solo puede contener hasta 127 bits", que de hecho es un montón de bits para un byte ;-). – sleske

+0

@joey oops !! lo siento . –

Respuesta

78

byte es un tipo de 1 byte por lo que puede variar entre -128 ... 127, por lo que la condición i < 128 siempre es cierto. Cuando se agrega 1 a 127 se desborda y se convierte en -128 y así sucesivamente en un bucle (infinito) ...

+6

¿esta respuesta realmente merece 26 votos? –

+5

@piemesons - ¡SÍ! – Mark

+2

@mark no lo creo. –

19

Después de 127, cuando se incrementa, se convertirá en -128, por lo que su condición no coincidirá.

bytes: El tipo de datos es un byte 8 bits entero con signo de complemento a dos. Tiene un valor mínimo de -128 y un valor máximo de 127 (inclusive). El tipo de datos byte puede ser útil para guardar la memoria en matrices grandes, donde el ahorro de memoria realmente importa. También se pueden usar en lugar de int donde sus límites ayudan a aclarar su código; el hecho de que el rango de una variable sea limitado puede servir como una forma de documentación.


Funcionará como esto:

0, 1, 2, ..., 126, 127, -128, -127, ... 

como 8 bits pueden representar un número firmado hasta 127.

Ver here para los tipos de datos primitivos.


imagen dice más que las palabras alt text

+2

126,127, -128, -127, ... Te perdiste uno. – Jorn

+0

@jorn yup:) ... –

11

Debido bytes se firman en Java por lo que se siempre ser inferior a 128.

Por qué Java eligió los bytes firmados como un misterio desde el fondo del tiempo. Nunca he sido capaz de entender por qué se corrompen un perfecto tipo de datos sin signo :-)

Tal vez puedas probar:

for (byte i = 0 ; i >= 0; ++i) { 

o, mejor aún:

for (int i = 0 ; i < 128; ++i) { 
+0

la única razón por la que se me ocurre es por consistencia, todos los otros tipos integrales están firmados, por lo que si 'byte' iba a estar sin firmar, entonces sería el único que salga. –

+0

Aunque el sistema de tipos comunes en .NET tiene una limitación similar a los tipos firmados, si recuerdo correctamente. – Joey

+0

¿soy yo o tu segundo fragmento es igual a lo que publicó el op? – fortran

7

porque cuando == 127 yy ejecuta i ++ se desborda a -128.

6

El tipo de byte tiene un rango de -128..127. Entonces i es siempre menos de 128.

2

mejor si lo haces

for (byte i = 0 ; i < Byte.MAX_VALUE; i++) { 
    System.out.println(i + 1 + " " + name); 
} 
+1

Mejor si desea contar de 0 a 126, es decir :-) – paxdiablo

1

esto debería funcionar

 for (byte i = 0 ; i<128; ++i) { 
     if(i==-128) 
      break; 
     System.out.println(i + 1 + " " + "name"); 
    } 
+0

-1, debido a dos problemas: 1: Eso no funcionará (desbordamiento: pasa a -128 sin pasar por 128) 2: Incluso sin el desbordamiento, el bloque de condición 'if (i == 128)' nunca se ejecutaría; si lo fuera, significaría que el bucle 'for' podría ingresarse incluso cuando su entrada condicional para entrada era falsa. –

+0

@jhominal Sí, no funcionará, lo siento. Mi respuesta inicial fue si (i == - 128), luego la edité en i == 128. Mi error. Lo he cambiado de nuevo. Ahora debería funcionar. :) –

+1

¿Por qué no reemplazar el bucle 'for' por' para (byte i = 0; i <128 && i! = - 128; ++ i) '? Eso eliminaría la declaración 'break'. –

3

bien, por lo que la razón detrás de esto ya ha sido contestado, pero en caso de que estaban interesados ​​en algunos antecedentes:

A bit es la unidad de almacenamiento más pequeña que la computadora puede reconocer (no es el número más pequeño). Un bit es 0 o 1.

A byte es un tipo de datos de 8 bits, lo que significa que se compone de cadenas de 8 bits como 10101010 o 0001110. Usando la combinatoria simple, sabemos que hay 2^8 = 256 combinaciones posibles de bytes.

Si solo quisiéramos representar números positivos, podríamos hacer una conversión directa de la base 2 a la base 10. La forma en que funciona es, para una cadena de bits b7b6b5b4b3b2b1b0, el número en decimal es dec = sum from n=0 to 7 of (bn * 2^n).

Al representar solamente números positivos (un unsigned byte) podemos representar 256 números posibles en el rango 0 a inclusive.

El problema aparece cuando queremos representar datos firmados. Un enfoque ingenuo (esto es, para fondo, no como lo hace Java) es tomar el bit más a la izquierda y convertirlo en el bit de signo donde 1 es negativo y 0 es positivo. Entonces, por ejemplo, 00010110 sería 21 y 10010110 sería -21.

Existen dos problemas principales con un sistema de este tipo. La primera es que 00000000 es 0 y 10000000 es -0, pero como todos saben, no hay -0 que sea diferente de 0, pero tal sistema permite el número y 0 ≠ -0. El segundo problema es que, debido a que representa dos ceros, el sistema solo permite representar números de -127 a 127, un rango de solo 254 (2 menos que antes).

Un sistema mucho mejor (y el que utilizan la mayoría de los sistemas) se llama Two's Compliment. En el cumplido de Two, los números positivos se representan con su cadena de bits normal donde el bit más a la izquierda es 0. Los números negativos se representan con el bit más a la izquierda como un 1 y luego se calcula el cumplido de los dos para ese número (de ahí el nombre)

Aunque matemáticamente es un proceso un poco más complejo, porque estamos tratando con el número 2 hay algunos atajos. Esencialmente, puedes tomar la versión positiva y (de derecha a izquierda) tomar todos los ceros hasta que toques un 1. Copia esos ceros y uno, luego toma el NOT del resto de los bits. Entonces, por ejemplo, para obtener -21, positivo 21 es 00010110 tomamos el 10 y no el resto para obtener 11101010, la representación complementaria de los dos de -21.Enviar

de Two es un sistema para captar mucho más difícil, pero evita los problemas mencionados anteriormente, y para un número de n bits puede representar todos los dígitos de -2^(n-1) a 2^(n-1)-1 que por nuestra byte significa -128 a 127 (de ahí el problema en esta pregunta)

Un par de notas:
- Esto es solo para la representación entera. La representación de números reales es otro sistema completo (si hay una solicitud para ello, estoy seguro de que podríamos hacer una representación numérica CW post)
- Wikipedia tiene un par más de sistemas de representación numérica si usted está interesado.

Cuestiones relacionadas