suma resta positivos positivo numeros negativos negativo mas left ejercicios ejemplos desplazar derecha corrimiento bitwise c bit-shift negative-number

resta - shift function in c



Desplazar a la derecha los nĂºmeros negativos en C (6)

A-1: Sí. 0xffff >> 1 es 0x7fff o 32767. No estoy seguro de lo que hace -0xffff. Eso es peculiar.

A-2: Cambiar no es lo mismo que dividir. Se trata de un cambio de bit, una operación binaria primitiva. Que a veces se puede usar para algunos tipos de división es conveniente, pero no siempre lo mismo.

Tengo un código C en el que hago lo siguiente.

int nPosVal = +0xFFFF; // + Added for ease of understanding int nNegVal = -0xFFFF; // - Added for valid reason

Ahora cuando intento

printf ("%d %d", nPosVal >> 1, nNegVal >> 1);

yo obtengo

32767 -32768

Es esto esperado?

Soy capaz de pensar algo como

65535 >> 1 = (int) 32767.5 = 32767 -65535 >> 1 = (int) -32767.5 = -32768

Es decir, -32767.5 se redondea a -32768.

¿Es este entendimiento correcto?


Cuando se desplaza hacia la derecha, se descarta el bit menos significativo.

0xFFFF = 0 1111 1111 1111 1111, que se desplaza a la derecha para dar 0 0111 1111 1111 1111 = 0x7FFF

-0xFFFF = 1 0000 0000 0000 0001 (complemento 2s), que se desplaza a la derecha a 1 1000 0000 0000 0000 = -0x8000


Debajo del nivel C, las máquinas tienen un núcleo de CPU que es enteramente entera o escalar . Aunque en la actualidad cada CPU de escritorio tiene una FPU, este no siempre era el caso, e incluso hoy en día los sistemas integrados se hacen sin instrucciones de coma flotante.

Los paradigmas de programación de hoy y los diseños de CPU e idiomas datan de la época en que la FPU ni siquiera existía.

Por lo tanto, las instrucciones de CPU implementan operaciones de punto fijo , generalmente tratadas como operaciones puramente enteras . Solo si un programa declara elementos de float o double existirán fracciones. (Bueno, puedes usar las operaciones de CPU para "punto fijo" con fracciones, pero eso es ahora y siempre fue bastante raro).

Independientemente de lo que requería un comité de estándares de idiomas hace años, todas las máquinas razonables propagan el bit de signo en los cambios a la derecha de los números con signo. Los cambios a la derecha de los valores sin signo cambian en ceros a la izquierda. Los bits desplazados a la derecha se dejan caer al suelo.

Para comprender mejor, deberá investigar "aritmética de dos poros".


La especificación C no especifica si el bit de signo está desplazado o no. Depende de la implementación.


No, no obtienes números fraccionarios como 0.5 cuando trabajas con enteros. Los resultados se pueden explicar fácilmente cuando observa las representaciones binarias de los dos números:

65535: 00000000000000001111111111111111 -65535: 11111111111111110000000000000001

El bit se desplaza hacia la derecha y se extiende a la izquierda (tenga en cuenta que esto depende de la implementación, gracias a Trent):

65535 >> 1: 00000000000000000111111111111111 -65535 >> 1: 11111111111111111000000000000000

Convertir de nuevo a decimal:

65535 >> 1 = 32767 -65535 >> 1 = -32768


Parece que su implementación probablemente está realizando un desplazamiento de bits aritmético con dos números de complemento. En este sistema, desplaza todos los bits hacia la derecha y luego rellena los bits superiores con una copia de lo que fue el último bit. Entonces para su ejemplo, tratando int como 32 bits aquí:

nPosVal = 00000000000000001111111111111111 nNegVal = 11111111111111110000000000000001

Después del turno, tienes:

nPosVal = 00000000000000000111111111111111 nNegVal = 11111111111111111000000000000000

Si convierte esto de nuevo a decimal, obtiene 32767 y -32768 respectivamente.

Efectivamente, un cambio a la derecha gira hacia el infinito negativo.

Editar: según la Sección 6.5.7 del último borrador del estándar , este comportamiento en números negativos depende de la implementación:

El resultado de E1 >> E2 es E1 posiciones de bit E2 desplazadas a la derecha. Si E1 tiene un tipo sin signo o si E1 tiene un tipo firmado y un valor no negativo, el valor del resultado es la parte integral del cociente de E1 / 2 E2 . Si E1 tiene un tipo firmado y un valor negativo, el valor resultante está definido por la implementación.

Su declarado rational para esto:

El Comité C89 afirmó la libertad en la implementación otorgada por K & R para no requerir que la operación de cambio de la derecha firmada se extienda, ya que tal requisito podría ralentizar el código rápido y dado que la utilidad de los cambios de signo extendido es marginal. (¡Cambiar un entero de complemento de dos negativo aritméticamente a la derecha no es lo mismo que dividir por dos!)

De modo que depende de la implementación en teoría. En la práctica, nunca he visto una implementación que no haga un desplazamiento aritmético cuando se firma el operando izquierdo.