contenido
1. Operaciones con bits y bases
2. Varias operaciones de bits interesantes
Un problema y tres soluciones: el número 1 en binario
Determinar si un número es un exponente de 2
Encuentre el número de pedidos
5. Mejorar el pensamiento de operación de bit
Intercambiar los bits de paridad de un entero
Representación binaria de números
Ocurre K veces y Ocurre una vez
1. Operaciones con bits y bases
Extraños trucos para operaciones con bits:
- Juzgando la paridad
- Obtener bit binario es 1 o 0
- Intercambiar los valores de dos variables enteras
- Encuentre el valor absoluto de un número entero sin usar una declaración de juicio
- Los operadores >> y << desplazan los bits a la derecha o a la izquierda
- >>> el operador llenará los bits altos con 0; >> el operador llena los bits altos con el bit de signo, sin operador <<<
- Para int, 1<<35 es lo mismo que 1<<3
- AND: ambos son 1, el resultado es 1; o: uno es 1, el resultado es 1; XOR: los dos no son iguales, el resultado es 1
a B ~ un a&b a|b a ^ b 1 1 0 1 1 0 0 1 1 0 1 1 0 0 1 0 0 0
2. Varias operaciones de bits interesantes
|
1. Convierta caracteres ingleses a minúsculas usando u operación y espacio
('a' | ' ') = 'a'
('A' | ' ') = 'a'
2. Use la operación AND &
y el guión bajo para convertir caracteres ingleses a mayúsculas
('b' & '_') = 'B'
('B' & '_') = 'B'
3. Use la operación XOR ^
y los espacios para intercambiar mayúsculas y minúsculas de caracteres ingleses
('d' ^ ' ') = 'D'
('D' ^ ' ') = 'd'
4. Determinar si dos números son del mismo signo
int x = -1, y = 2;
boolean f = ((x ^ y) < 0); // true
int x = 3, y = 2;
boolean f = ((x ^ y) < 0); // false
5. Intercambia dos números sin variables temporales
int a = 1, b = 2;
a ^= b;
b ^= a;
a ^= b;
// a = 2, b = 1
6. Agrega uno
int n = 1;
n = -~n;
// n = 2
7. menos uno
int n = 2;
n = ~-n;
// n = 1
pd: la operación anterior se puede usar para copas frente a amigos, pero no tiene ningún uso práctico.
3. Usa n&(n-1)
n &(n-1)
Esta operación es común en los algoritmos y actúa para eliminar n
el último 1 en la representación binaria de un número .
La lógica central es que n - 1
debe ser posible eliminar el último 1 y, al mismo tiempo, cambiar los 0 subsiguientes en 1, de modo que la operación de suma se n
realice nuevamente &
, y solo el último 1 se pueda convertir en 0.
Aquí hay un ejemplo de cómo usarlo:
Un problema y tres soluciones: el número 1 en binario
Método 1: el entero n es bit a bit y 1, es decir, n&1, (bit a bit y: el resultado es 1 para ser 1), cuando n se expresa en binario como el 1 más a la derecha, entonces n&1 es 1, cuenta ++ una vez, y luego n Mover a la derecha >> comparar uno por uno.
Ir directamente al código:
#include<stdio.h>
int main()
{
int n;
int ants = 0;
scanf("%d",&n);
for (int i = 0; i < 32; i++)
{
int m = n;
if ((m>>i)&1== 1)
ants++;
}
printf("%d", ants);
return 0;
}
Método 2: similar al método, es decir, mantenga el número entero n sin cambios y mueva 1 a la izquierda; el código no se proporciona aquí y le interesa probarlo.
Método 3: use el n&n(-1) explicado anteriormente, que no se explicará en detalle aquí, puede ver lo anterior
int hammingWeight(int n) {
int res = 0;
while (n != 0) {
n = n & (n - 1);
res++;
}
return res;
}
Determinar si un número es un exponente de 2
Si un número es un exponente de 2, su representación binaria debe contener solo un 1 :
2^0 = 1 = 0b0001
2^1 = 2 = 0b0010
2^2 = 4 = 0b0100
Si n & (n-1)
la técnica utilizada es muy simple (tenga en cuenta la precedencia del operador, los paréntesis no se pueden omitir):
boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
return (n & (n - 1)) == 0;
}
una pequeña prueba
>>>El índice de 2 (el código del título se muestra arriba, si tiene alguna pregunta, puede discutirla en el área de comentarios)
4. Para usar a ^ a = 0
La naturaleza de la operación XOR es algo que debemos tener en cuenta:
El resultado de la operación XOR entre un número y sí mismo es 0, es decir a ^ a = 0
, el resultado de la operación XOR entre un número y 0 es él mismo, es decir a ^ 0 = a
.
Encuentre el número de pedidos
Para esta pregunta, mientras hacemos XOR todos los números, los números emparejados se convertirán en 0. El XOR del número único y 0 sigue siendo el mismo, por lo que el resultado final de XOR es el elemento que solo aparece una vez:
int singleNumber(int[] nums) {
int res = 0;
for (int n : nums) {
res ^= n;
}
return res;
}
una pequeña prueba
>>> un número que solo aparece una vez
5. Mejorar el pensamiento de operación de bit
Intercambiar los bits de paridad de un entero
El intercambio de paridad de enteros aquí es en realidad el intercambio de bits de paridad en binario. En lugar del intercambio de paridad en decimal, 15, reemplácelo con 51. Por ejemplo, reemplace 1010 con 0101;
Idea: ingrese un número entero, hágalo bit a bit y 010101... mantenga el valor del número par como ou (esta oración necesita gusto), y luego hágalo bit a bit y 101010... mantenga el valor impar como ji, luego mueva ou a la izquierda << un bit, ji a la derecha >> un bit, y luego XOR para lograr el propósito deseado.
Código:
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int ji = n & 0xaaaaaaaa;//1010...
int ou = n & 0x55555555;//0101...
int c= (ou << 1) ^(ji >> 1);
printf("%d",c);
return 0;
}
representación binaria de números reales de punto flotante
Código:
0.625 0.5+0.125
0.101
#include<iostream>
using namespace std;
int main()
{
double n;
cin >> n;
string s1 = "0.";
while (n > 0)
{
n= n * 2;
if (n >=1)
{
s1 +="1";
n = n - 1;
}
else {
s1 += "0";
n = n;
}
if (s1.size() > 34)
{
cout << "ERROR " << endl;
}
}
cout << s1 << endl;
return 0;
}
Ocurre K veces y Ocurre una vez
El gran avance para resolver el problema: la conclusión de que el resultado es 0 usando k números K-arios para sumar sin llevar
Primero convierta el número decimal a k-ario, y use la cadena para almacenar en orden
inverso.Use el método de resto de dividir por k (un método de cálculo general) para convertir el número en la matriz a k-ario.Debido a que debe calcularse por bit (columna) después de la conversión a k-ario, se almacena en forma de cadena. Después de la conversión al sistema k-ario, debido a los diferentes tamaños de los números, las longitudes también pueden ser diferentes. Aunque la suma es 0 para números con k números, no hay diferencia, pero la secuencia de bits es muy importante para el requerido número, (cálculo Cuando la cadena se calcula de izquierda a derecha, y cuando se vuelve a convertir a decimal, se calcula de derecha a izquierda), por lo que los números convertidos a k-base se almacenan en orden inverso .
Encuentre la longitud máxima de la cadena y luego complete la cadena que es menor que maxlen.
Debido a que debe calcularse columna por columna, es necesario saber cuántas columnas hay como máximo, es decir, maxlen. Rellene "0" en el orden superior, compense la longitud máxima, para hacer una suma poco a poco sin llevarSuma sin acarreo
Suma estos números sin acarreo, que es equivalente a la operación XOR ^, o toma el número después de la suma bit a bit módulo kResultado de salida, K-ario a decimal
Este paso es simple, el mismo principio que el común octal a decimal y hexadecimal a decimal.
#include<iostream>
#include<algorithm>
#include<string>
//#include<cmath>
using namespace std;
string decTok(int dec, int k); //十进制数转K进制
int kTodec(string str, int k); // K进制转十进制
string decTok(int dec, int k)
{
string ret = ""; //作为结果
while (dec > 0) {
ret += char(dec%k + '0');//如:5+'0'='5'
dec /= k;
}
reverse(ret.begin(), ret.end());//翻转
return ret;
}
int kTodec(string str, int k)
{
int ans = 0;
for (int i = 0; i < str.size(); i++)
ans = ans * k + (str[i] - '0');//020 首位是最高位
return ans;
}
int main()
{
int n[] = { 1,1,1,3,3,3,5,5,5,9,9,9,6,7,7,7 };
int k = 3; //根据数组数据,要转换的进制
//1.十进制数转K进制
string str[16];
for (int i = 0; i < 16; i++)
str[i] = decTok(n[i], k);
//2.找出16条字符串中最大长度
int maxlen = 0;
int len;
for (int i = 0; i < 16; i++) {
len = str[i].size();
maxlen = max(maxlen, len); //maxlen=max(maxlen,str[i].size())
}
//16条字符串中,若字符串长度<maxlen,则进行补齐,以便逐位做不进位加法
for (int i = 0; i < 16; i++)
while (str[i].size() < maxlen)
str[i] = "0" + str[i];
//ans:结果初始化
string ans = "";
while (ans.size() < maxlen)
ans += "0";
//3.做不进位加法
for (int i = 0; i < 16; i++)
for (int j = 0; j < maxlen; j++)
ans[j] = char(((str[i][j] - '0') + (ans[j] - '0')) % k + '0');
cout << ans << endl; //ans字符串结果
cout<< kTodec(ans, k); //转为十进制数
return 0;
}