aritmética bit a bit

Prefacio

Las operaciones de bits juegan un papel importante en nuestro aprendizaje: a partir del almacenamiento de números binarios, necesitamos realizar operaciones de bits.

1. Revisión de operaciones de bits.

1. Revisión de la operación de bits

Bit a bit AND (&) : si ambos bits binarios correspondientes son 1, el valor resultante del bit es 1; de lo contrario, es 0
Bit a bit OR (|) : si uno de los dos bits binarios correspondientes es 1, el valor resultante del bit es 1, de lo contrario 0
XOR bit a bit (^) : si dos bits binarios correspondientes tienen el mismo valor, el valor resultante del bit es 0; de lo contrario, 1
Inverso bit a bit (~) : invierte el número binario bit a bit, es decir, 0 se convierte en 1 y 1 se convierte en 0.
Insertar descripción de la imagen aquí
Entre ellos, la operación XOR es la que más utilizamos, y la operación XOR también se puede llamar suma sin acarreo.
Insertar descripción de la imagen aquí

2. Operaciones de bits comunes

1. Reglas de operación de XOR

1. El resultado XOR de dos números idénticos es 0.
2. XOR satisface la ley conmutativa
3. El resultado XOR de cualquier número es el número mismo.
Insertar descripción de la imagen aquí

2. Obtener el opuesto de un número

El inverso de este número más 1 es el opuesto de este número, es decir ( -num = (~num + 1) )
Insertar descripción de la imagen aquí

3. Obtenga el 1 más a la derecha del dígito binario en un número.

A este número se le aplica un AND bit a bit con su número opuesto, es decir (num &= -num).
Insertar descripción de la imagen aquí
Agregaremos otras operaciones a continuación.

2. Ejercicios de operación de bits

1. Intercambiar los valores de dos números sin crear una tercera variable.

void Swap()
{
    
    
	int a = 10;
	int b = 20;
	printf("交换前:a = %d,b = %d\n", a, b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("交换后:a = %d,b = %d\n", a, b);
}

Insertar descripción de la imagen aquí
En este momento, el XOR del mismo número se usa como 0, y cualquier número XOR de 0 es ese número.
Tenga en cuenta que los valores de la operación XOR pueden ser los mismos, pero el valor XOR del mismo espacio no puede ser XOR, de lo contrario se convertirá en 0. Por ejemplo, realice XOR en a al mismo tiempo.
Resultados de la prueba:
Insertar descripción de la imagen aquí
ejercicios relacionados

2. Devuelve un número mayor sin utilizar operaciones de comparación

void Compare()
{
    
    
	int a = 10;
	int b = 20;
	int c = a - b;
	int sya = ((a >> 31) & 1);//获得a的符号位
	int syb = ((b >> 31) & 1);//获得b的符号位
	int syc = ((c >> 31) & 1);//获得c的符号位
	int dif = sya ^ syb;//判断a和b的符号位是否相同
	//符号位相同则不会产生溢出
	if (dif == 0)
	{
    
    
		if (syc == 1)
		{
    
    
			printf("最大值为:%d\n", b);
		}
		else
		{
    
    
			printf("最大值为:%d\n", a);
		}
	}
	//可能会产生溢出
	else
	{
    
    
		if (sya == 1 && syb == 0)
		{
    
    
			printf("最大值为:%d\n", b);
		}
		else
		{
    
    
			printf("最大值为:%d\n", a);
		}
	}
}

Resultados de la prueba:
Insertar descripción de la imagen aquí

Tenga en cuenta que la suma o resta de dos números puede provocar un desbordamiento. Tomemos char como ejemplo: otro ejemplo
Insertar descripción de la imagen aquí
:
Insertar descripción de la imagen aquí
por lo tanto, esto requiere que juzguemos si se producirá un desbordamiento y esto devuelve directamente si el resultado de restar dos números es mayor que 0. no se aplica en situaciones de desbordamiento.
operación de práctica

3. No utilice símbolos como suma, resta, multiplicación y división para realizar las operaciones correspondientes.

1. Adición

//加法
int Add(int a, int b)
{
    
    
	int sum = a;
	while (b != 0)
	{
    
    
		sum = a ^ b;
		//获得要进行进位的位置
		b = (a & b) << 1;
		a = sum;
	}
}

Insertar descripción de la imagen aquí
Resultado de la prueba:
Insertar descripción de la imagen aquí
sumamos XOR sin acarreo, por lo que se aplica AND a los dos números siguientes para encontrar la posición donde ambos números son 1, y el desplazamiento a la derecha equivale a avanzar 1 en XOR.

2. Resta

//减法
int Sub(int a, int b)
{
    
    
	//获得b的相反数
	int sum = Add(~b, 1);
	//a和b的相反数进行相加
	sum = Add(a, sum);
	return sum;
}

Resultado de la prueba:
Insertar descripción de la imagen aquí
aquí podemos obtener el número opuesto que queremos a través de nuestra función agregar. El principio es que sumamos 1 a la inversión bit a bit para obtener

3. Multiplicación

//乘法
int Mul(int a, int b)
{
    
    
	int sum = 0;
	while (b != 0)
	{
    
    
		if ((b & 1) != 0)
		//b当前最右侧的是否为1
		{
    
    
			sum = Add(sum, a);
		}
		//模拟相乘的过程
		a <<= 1;//a进行右移
		b >>= 1;//b进行左移
	}
	return sum;
}

Resultados de la prueba:
Insertar descripción de la imagen aquí
principio: la multiplicación binaria es lo mismo que la multiplicación decimal, aquí convertimos la multiplicación decimal en multiplicación binaria y podemos obtener cada número agregado cambiando
Insertar descripción de la imagen aquí

4. División

//除法
int div(int a, int b)
{
    
    
	int x = a < 0 ? Add(~a, 1) : a;
	int y = b < 0 ? Add(~b, 1) : b;
	int sum = 0;
	int i = 0;
	//从第31位开始进行判断
	for (i = 31; i > -1; i = Sub(i, 1))
	{
    
    
		if ((x >> i) >= y)
		{
    
    
			sum |= (1 << i);
			x = Sub(x, y << i);
		}
	}
	return ((a < 0) ^ (b < 0)) ? Add(~sum, 1) : sum;
}
int Div(int a, int b)
{
    
    
	if (b == 0)
	{
    
    
		//0为除数,结束程序
		exit(-1);
	}
	if (a == INT_MIN && b == INT_MIN)
	{
    
    
		return 1;
	}
	else if (b == INT_MIN)
	{
    
    
		return 0;
	}
	else if (a == INT_MIN)
	{
    
    
		int sum = div(Add(a, 1), b);
		sum = Add(sum, div(Sub(a, Mul(sum, b)), b));
		return sum;
	}
	else
	{
    
    
		return div(a, b);
	}
}

Resultados de la prueba:
Insertar descripción de la imagen aquí
Principio:
Insertar descripción de la imagen aquí
Nota: Al moverse, preste atención a la situación de desbordamiento y si el divisor es 0.

4. El número de unos en el sistema binario entero.

void Sum1()
{
    
    
	int a = 20;
	int sum = 0;
	while (a != 0)
	{
    
    
		a &= (a - 1);
		sum++;
	}
	printf("1的个数为%d个\n", sum);
}

Insertar descripción de la imagen aquí
De lo anterior se puede ver que nuestra operación (a &= (a - 1)) es eliminar 1
resultado de la prueba:
Insertar descripción de la imagen aquí
Práctica de preguntas

5. Encuentre un número que aparezca una vez en una matriz donde otros números aparecen dos veces.

void Single_num()
{
    
    
	int arr[] = {
    
     1,1,2,2,3,4,4,5,5,6,6 };
	int sum = 0;
	int i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
    
    
		sum ^= arr[i];
	}
	printf("出现一次的数%d\n", sum);
}

Esta es la ley conmutativa que utilizamos y el resultado XOR de dos números idénticos es 0.
Resultados de la prueba:
Insertar descripción de la imagen aquí
preguntas de práctica

6. Encuentra dos números que aparecen una vez en una matriz en la que otros números aparecen dos veces.

void two_Single_num()
{
    
    
	int arr[] = {
    
     1,1,2,2,3,4,5,5,6,6 };
	int sum = 0;
	int i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
    
    
		//找到这两个出现一次的数
		sum ^= arr[i];
	}
	//获得这两数异或结果最右侧的1,这个1也是这两个数不相同的位置
	int sum1 = sum & (~sum + 1);
	int sum2 = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
    
    
		//&的优先级低于 ==
		//把和这个不相同的一位的值进行按位与,如果结果为0;则可以分为1组
		if ((sum1 & arr[i]) == 0)
		{
    
    
			//得到的为其中的一位
			sum2 ^= arr[i];
		}
	}
	printf("出现一次的数%d %d\n", sum^sum2,sum2);
}

Resultados de la prueba:
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
preguntas de práctica

7. Encuentra el número que aparece una vez en una matriz en la que otros números aparecen K veces.

void k_Single_num()
{
    
    
	int arr[] = {
    
     5, 4, 1, 1, 5, 1, 5 };
	int k = 3; 
	int x = 0;
	int a[32] = {
    
     0 };
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
    
    
		//把数组中的数的每个进制位都进行相加
		x = arr[i];
		for (int j = 31; j >= 0; j--) 
		{
    
    
			if (x & 1)
				a[j]++;
			x >>= 1;
		}
	}
	x = 0;
	for (int i = 0; i < 32; i++) 
	{
    
    
		//对我们相加的值的每一个进制位进行相应的取模运算就是我们所要的值了
		x <<= 1;
		x += a[i] % k;
	}
	printf("%d\n", x);
}

Resultados de la prueba:
Insertar descripción de la imagen aquí
Principio:
Insertar descripción de la imagen aquí
Podemos ver que el valor en nuestra i-ésima posición es ((a[i] + b[i]) % 5). De manera similar, los dos números en la base K están en la posición i. No hay un bit de resultado de suma de acarreo ((a[i] + b[i]) % K), por lo que cuando se suman k K-dígitos idénticos, cada bit del resultado agregado es 0. Entonces, establecemos el número de apariciones en los dígitos de base K correspondientes y finalmente convertimos el resultado de la suma a notación decimal para obtener el valor que necesitamos.

Práctica de preguntas

Resumir

Hay muchas más preguntas sobre operaciones de bits, puedes encontrarlas a continuación para practicar.

Supongo que te gusta

Origin blog.csdn.net/2301_76986069/article/details/132776030
Recomendado
Clasificación