ฉันต้องการแยกบิตของตัวเลขทศนิยม
ตัวอย่างเช่น 7 คือไบนารี 0111 และฉันต้องการรับ 0 1 1 1 บิตทั้งหมดที่เก็บไว้ในบูล ฉันจะทำเช่นนั้นได้อย่างไร?
ตกลงการวนซ้ำไม่ใช่ตัวเลือกที่ดีฉันจะทำอย่างอื่นได้ไหม
ฉันต้องการแยกบิตของตัวเลขทศนิยม
ตัวอย่างเช่น 7 คือไบนารี 0111 และฉันต้องการรับ 0 1 1 1 บิตทั้งหมดที่เก็บไว้ในบูล ฉันจะทำเช่นนั้นได้อย่างไร?
ตกลงการวนซ้ำไม่ใช่ตัวเลือกที่ดีฉันจะทำอย่างอื่นได้ไหม
คำตอบ:
ถ้าคุณต้องการบิต k ของ n ให้ทำ
(n & ( 1 << k )) >> k
ที่นี่เราสร้างมาสก์ใช้มาสก์กับ n แล้วเลื่อนค่ามาสก์ไปทางขวาเพื่อให้ได้บิตที่เราต้องการ เราสามารถเขียนมันออกมาได้ครบถ้วนมากขึ้นเป็น:
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับบิตกำบังที่นี่
นี่คือโปรแกรม:
#include <stdio.h>
#include <stdlib.h>
int *get_bits(int n, int bitswanted){
int *bits = malloc(sizeof(int) * bitswanted);
int k;
for(k=0; k<bitswanted; k++){
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
bits[k] = thebit;
}
return bits;
}
int main(){
int n=7;
int bitswanted = 5;
int *bits = get_bits(n, bitswanted);
printf("%d = ", n);
int i;
for(i=bitswanted-1; i>=0;i--){
printf("%d ", bits[i]);
}
printf("\n");
}
struct
ก็มีประโยชน์เช่นกันเนื่องจากคุณได้รับข้อมูลที่ต้องการทั้งหมดด้วยการดำเนินการเพียงครั้งเดียว
ตามที่ร้องขอฉันตัดสินใจที่จะขยายความคิดเห็นของฉันเกี่ยวกับคำตอบของนิ้วชี้เพื่อเป็นคำตอบที่ครบถ้วนสมบูรณ์ แม้ว่าคำตอบของเขาจะถูกต้อง แต่ก็ซับซ้อนโดยไม่จำเป็น นอกจากนี้คำตอบปัจจุบันทั้งหมดยังใช้int
เครื่องหมาย s เพื่อแสดงค่า สิ่งนี้เป็นอันตรายเนื่องจากการเปลี่ยนค่าเชิงลบไปทางขวาถูกกำหนดให้ใช้งานได้ (เช่นไม่สามารถพกพาได้) และการเลื่อนไปทางซ้ายอาจนำไปสู่พฤติกรรมที่ไม่ได้กำหนด (ดูคำถามนี้ )
1
โดยทางด้านขวาขยับบิตที่ต้องการเข้ามาในตำแหน่งบิตอย่างมีนัยสำคัญน้อยกำบังสามารถทำได้ด้วย ไม่จำเป็นต้องคำนวณค่ามาสก์ใหม่สำหรับแต่ละบิต
(n >> k) & 1
ในฐานะโปรแกรมที่สมบูรณ์การคำนวณ (และการพิมพ์ในภายหลัง) อาร์เรย์ของค่าบิตเดียว:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned
input = 0b0111u,
n_bits = 4u,
*bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
bit = 0;
for(bit = 0; bit < n_bits; ++bit)
bits[bit] = (input >> bit) & 1;
for(bit = n_bits; bit--;)
printf("%u", bits[bit]);
printf("\n");
free(bits);
}
สมมติว่าคุณต้องการคำนวณบิตทั้งหมดเช่นในกรณีนี้และไม่ใช่เฉพาะการวนซ้ำสามารถเปลี่ยนเป็น
for(bit = 0; bit < n_bits; ++bit, input >>= 1)
bits[bit] = input & 1;
สิ่งนี้ปรับเปลี่ยนinput
ในสถานที่และด้วยเหตุนี้จึงช่วยให้สามารถใช้ความกว้างคงที่กะบิตเดียวซึ่งอาจมีประสิทธิภาพมากกว่าในบางสถาปัตยกรรม
นี่เป็นวิธีหนึ่งที่ทำได้ - มีวิธีอื่น ๆ อีกมากมาย:
bool b[4];
int v = 7; // number to dissect
for (int j = 0; j < 4; ++j)
b [j] = 0 != (v & (1 << j));
ยากที่จะเข้าใจว่าเหตุใดจึงไม่ต้องการใช้ลูป แต่มันง่ายพอที่จะคลายการวนซ้ำ:
bool b[4];
int v = 7; // number to dissect
b [0] = 0 != (v & (1 << 0));
b [1] = 0 != (v & (1 << 1));
b [2] = 0 != (v & (1 << 2));
b [3] = 0 != (v & (1 << 3));
หรือการประเมินนิพจน์คงที่ในสี่คำสั่งสุดท้าย:
b [0] = 0 != (v & 1);
b [1] = 0 != (v & 2);
b [2] = 0 != (v & 4);
b [3] = 0 != (v & 8);
นี่เป็นวิธีที่ง่ายมากที่จะทำ
int main()
{
int s=7,l=1;
vector <bool> v;
v.clear();
while (l <= 4)
{
v.push_back(s%2);
s /= 2;
l++;
}
for (l=(v.size()-1); l >= 0; l--)
{
cout<<v[l]<<" ";
}
return 0;
}
@prateek ขอบคุณสำหรับความช่วยเหลือ ฉันเขียนฟังก์ชันใหม่พร้อมความคิดเห็นเพื่อใช้ในโปรแกรม เพิ่ม 8 สำหรับบิตเพิ่มเติม (สูงสุด 32 สำหรับจำนวนเต็ม)
std::vector <bool> bits_from_int (int integer) // discern which bits of PLC codes are true
{
std::vector <bool> bool_bits;
// continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
for (int i = 0; i < 8; i++)
{
bool_bits.push_back (integer%2); // remainder of dividing by 2
integer /= 2; // integer equals itself divided by 2
}
return bool_bits;
}
หากคุณไม่ต้องการวนซ้ำคุณจะต้องเขียนมันออกมา:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 7;
#if 0
bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
#else
#define BTB(v,i) ((v) & (1u << (i))) ? true : false
bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
#undef BTB
#endif
printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);
return 0;
}
ดังที่แสดงไว้ที่นี่สิ่งนี้ยังใช้งานได้ในตัวเริ่มต้น
#include <stdio.h>
int main(void)
{
int number = 7; /* signed */
int vbool[8 * sizeof(int)];
int i;
for (i = 0; i < 8 * sizeof(int); i++)
{
vbool[i] = number<<i < 0;
printf("%d", vbool[i]);
}
return 0;
}
การใช้ std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
(n >> k) & 1
มีความถูกต้องเท่าเทียมกันและไม่ต้องใช้การคำนวณมาสก์เนื่องจากมาสก์มีค่าคงที่เนื่องจากการขยับก่อนการมาสก์แทนที่จะใช้วิธีอื่น