Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Duda con operadores a nivel de bits

Hola, estoy estudiando java, y aunque he visto mil y un artículos sobre los operadores de desplazamiento a nivel de bits >> y <<, comprendo cómo funcionan, pero no logro comprender en que situaciones verdaderamente se usan y bajo que conceptos. ¿Alguien sería tan amable de explicármelo con algún ejemplo sencillo detallando el por qué se necesita en ese caso en concreto? Muchísimas gracias por adelantado.

abril 30, 2014 | Registered Commenterknubbe

Se usan cuando el rendimiento es crítico, por ejemplo en codecs de audio y vídeo.
Para un uso "normal" no son realmente necesarios: lo poco que se gana en rendimiento, se pierde en claridad.

http://www.roseindia.net/java/master-java/bitwise-bitshift-operators.shtml

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

abril 30, 2014 | Registered Commenterchoces

Gracias, pero me quedo igual que estaba jajaja, yo comprendo en qué consiste, pero no le encuentro utilidad, es eso lo que me gustaría comprender, ya que estoy siguiendo algunos ejemplos de un proyecto en los cuales estoy viendo estos operadores. Quizá no tenga la mente suficientemente abierta aún y pido disculpas.

Por ejemplo, pongo un trozo donde usan esto:

public int yOffset = 0;

for (int yTile = yOffset >> 3; yTile <= (yOffset + height) >> 3; yTile++) {
int yMin = yTile * 8 - yOffset;
int yMax = yMin + 8;
if (yMin < 0)
yMin = 0;
if (yMax > height)
yMax = height;

¿Qué utilidad tiene ahí?

abril 30, 2014 | Registered Commenterknubbe

Guenas.

Un desplazamiento de 1 hacia la izquierda equivale a multiplicar por 2. Un desplazamiento de 1 bit hacia la derecha equivale a dividir por 2

Si no me equivoco, en este caso que muestras los desplazamientos a la derecha equivalen a dividir por 8. Fijate que es una división entera y jamas dará decimales sin necesidad de conversiones ni cosas raras.

Un saludo

abril 30, 2014 | Unregistered CommenterPaposo

¿No se ve así más claro?.
En mi sistema, tras 1 millón de iteraciones, la diferencia en ejecución es de 1ms, para el total de iteraciones.
Creo que no vale la pena la diferencia de claridad en el código, comparado con la diferencia en ejecución.

public class NewMain {

public static void main(String[] args) {
int yOffset = 10;
int height = 100;

for (int i = 0; i < 1_000_000; i++) {
conOperadores(yOffset, height);
sinOperadores(yOffset, height);
}

long currentTimeMillisCon = System.currentTimeMillis();
for (int i = 0; i < 1_000_000; i++) {
conOperadores(yOffset, height);
}
System.out.println("con operadores= " + (System.currentTimeMillis() - currentTimeMillisCon));

long currentTimeMillisSin = System.currentTimeMillis();
for (int i = 0; i < 1_000_000; i++) {
sinOperadores(yOffset, height);
}
System.out.println("con operadores= " + (System.currentTimeMillis() - currentTimeMillisSin));
}

private static void sinOperadores(int yOffset, int height) {
for (int yTile = 1; yTile <= 13; yTile++) {
int yMin = yTile * 8 - yOffset;
int yMax = yMin + 8;
if (yMin < 0) {
yMin = 0;
}
if (yMax > height) {
yMax = height;
}
}
}

private static void conOperadores(int yOffset, int height) {
for (int yTile = yOffset >> 3; yTile <= (yOffset + height) >> 3; yTile++) {
int yMin = yTile * 8 - yOffset;
int yMax = yMin + 8;
if (yMin < 0) {
yMin = 0;
}
if (yMax > height) {
yMax = height;
}
}
}
}

abril 30, 2014 | Registered Commenterchoces

Por si acaso...

int yTile = yOffset / 8, que es 1 en este caso
yTile <= (yOffset + height) / 8 que es 13 en este caso

Al asignarse el resultado a un int, los decimales se desprecian.

abril 30, 2014 | Registered Commenterchoces

Mil gracias a los 2, creo que ya he comprendido el por qué usa ese operador, según lo que he podido razonar con el ejemplo de choces y con la explicación de paposo, ya que esto es un juego que trabaja con píxeles, se utiliza a la hora de renderizar, ya que son 8x8 y >> 3 seria dividir por 8,lo utilizan en esta parte del programa para reducir tiempo de ejecución. A groso modo, ¿podría decirse que mi razonamiento es correcto?

abril 30, 2014 | Unregistered CommenterKnubbe

Buenas,

Normalmente se utiliza en campos muy especificos, en los que es necesario trabajar a nivel de bits. Por ejemplo en criptografia (encriptacion, compresion), graficos, redes(checksums, paridad, etc)....
En otros lenguajes, como C, veras muchos ejemplos sobre todos para almacenar bit fields. Esta tecnica permite utilizar todos los bits de un int, por ejemplo, como si de flags se tratase, aplicando desplazamiento y mascaras. De esta forma se ahorra mucho espacio, algo muy util cuando las memorias eran muy limitadas.

En Java esta tecnica no es tan habitual, pero se utiliza por ejemplo para almacenar la informacion RGB de las imagenes:
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#TYPE_INT_ARGB

Asi, en una imagen la operacion para extraer informacion de cada pixel seria:


(pixel >> 16) & 0xFF ==> Rojo
(pixel >> 8) & 0xFF ==> Verde
(pixel >> 0) & 0xFF ==> Azul
(pixel >> 24) & 0xFF ==> Canal alfa

De cualquier forma, este tipo de tecnicas se utiliza cada vez menos por los motivos que indica choces.


Un saludo

abril 30, 2014 | Unregistered CommenterUnoPorAhi

Ahhh claro, leyendo lo del RGB ya tiene todo muchísimo mas sentido, menos mal, porque me estaba volviendo un poco loco ya y se me estaba haciendo muy cuesta arriba... Sólo me queda agradeceros eternamente vuestra colaboración en mi aprendizaje :), un saludo a todos

abril 30, 2014 | Unregistered CommenterKnubbe

Guenas.

Lo que ha escrito choces es lo mas eficiente.

El tio que ha escrito el código que has puesto no se ha puesto a pensar que buena parte del código que recalcula da un resultado constante.

Mira, antes de optimizar pedacítos de código mira las invariantes que cada parte trata.
Sobre todo en bucles. Te he expresado un motivo por el cual se usa este sistema. Unoporahi lo ha dejado aun mas claro, y choces te ha levantado la idea de que no hace falta optimizar el código interno si es invariable.

Consejo: Para diseñar hazlo de arriba a abajo, y para optimizar de dentro a afuera (con cerebro, teniendo en cuenta las invariantes). Si lo que quieres es un código muy rápido te aconsejo que hagas uso del termino "final". Si ese parámetro no va a cambiar dentro de la rutina, declararlo como final ayuda mucho al compilador a optimizar el código.

Son chorraditas, pero te prometo que optimizar el código de un bucle, dentro de un bucle, dentro de un bucle te va a proporcionar resultados inimaginables.

Un saludo

mayo 2, 2014 | Unregistered CommenterPaposo