If you have a binary number (10101100 - used for bits in a byte) what is the best way to check which position is a 1 or a 0?
Printable View
If you have a binary number (10101100 - used for bits in a byte) what is the best way to check which position is a 1 or a 0?
Take that vaue and AND it with a mask
10101100 AND 00100000 = 00100000
10101100 AND 01000000 = 00000000
If the product is zero, then that bit isnt set
Ok, then how come when I run the following code, the binary 10 shows "-----!-!" where - is 0 and ! is 1.
Code:if(tempBinValue & 10000000) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 1000000) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 100000) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 10000) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 1000) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 100) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 10) {
cout << "!";
}else{
cout << " ";
}
if(tempBinValue & 1) {
cout << "!";
}else{
cout << " ";
}
cout << " " << binValue << endl;
You should be using a bitmask not an integer, i.e. instead of 1 use 0x01, instead of 10 use 0x02, 100 - 0x04 1000 - 0x08 10000 - 0x10, 100000 - 0x20, 1000000 - 0x40 and 10000000 - 0x80.
so, I should be doing something like (tempBitValue & 0x01) instead?
Here is some of my code chopped out:
For a line of 11111111 it's returning 11000111 when I run this... what's going on? It should return 11111111.Code:const unsigned char bit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
//stuff...
for(int i=0; i < (imageWidth * imageLength); i++)
{
int binValue = binaryConv(buf[i]);
int tempBinValue = binValue;
for(int j = 0; j < 8; j++)
{
if(tempBinValue & bit[j])
{
cout << "!";
}else{
cout << " ";
}
}
cout << " " << binValue << endl;
if((i % imageWidth) == 1) cout << endl;
}
This worked fine for me, dont have your buffer to test it on though.
Btw, why do you doCode:const unsigned char bit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
int tempBinValue = 255;
for(int j = 0; j < 8; j++)
{
if(tempBinValue & bit[j])
{
cout << "1 ";
}
else
{
cout << "0 ";
}
}
cout << endl;
and not just,Code:int binValue = binaryConv(buf[i]);
int tempBinValue = binValue;
Code:int tempBinValue = binaryConv(buf[i]);
When your code returns 11000111 what is the binValue then ?
Yeah the
was for something else, but I changed it toCode:int binValue = binaryConv(buf[i]);
int tempBinValue = binValue;
now. Thanks.Code:int tempBinValue = binaryConv(buf[i]);
When it returns 11000111 binValue = 11111111
It's very strange... only 0 and a few others work, but others don't. I don't understand why some do and some don't.
Ok, here is my full code. The part between the //---- s is most likely what is going to need attention. But I included the rest incase I'm overlooking something else.
Here is another part of the code you might want to look at (just in case it's got something wrong with it -- but I don't think it does) This is the part where it converts a decimal number to binary.Code:int bitonal() {
uint32 imageWidth, imageLength;
int stripMax, stripCount;
unsigned long imageOffset, result, bufferSize;
tsize_t stripSize;
char* fileName = "10x10bi.tif";
TIFF* tif = TIFFOpen(fileName, "r");
if (tif) {
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
m_memoryWidth = (imageWidth + (1/2)) / 8;
m_memoryLength = imageLength;
// Read in the possibly multiple strips
stripSize = TIFFStripSize(tif);
stripMax = TIFFNumberOfStrips(tif);
imageOffset = 0;
bufferSize = m_memoryWidth * m_memoryLength;
m_bufferSize = bufferSize;
unsigned char* buf = new unsigned char[bufferSize];
const unsigned int bit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for (stripCount = 0; stripCount < stripMax; stripCount++){
if((result = TIFFReadEncodedStrip (tif, stripCount,
buf + imageOffset,
stripSize)) == -1){
fprintf(stderr, "Read error on input strip number %d\n", stripCount);
exit(42);
}
imageOffset += result;
}
//------------------------ERRORS?
for(int i=0; i < (imageWidth * imageLength); i++)
{
int binValue = binaryConv(buf[i]);
for(int j = 0; j < 8; j++)
{
if(binValue & bit[j])
{
cout << 1;
}else{
cout << 0;
}
}
cout << " " << binValue << endl;
}
//-------------------------
}
return 0;
}
Code:int binaryConv(int number) {
int result = 0;
////////////////////////////////////////////////////////////////////
// Input
////////////////////////////////////////////////////////////////////
int numCopy = number;
if (number > 255 || number < 0) {
cout << "ERROR: Number cannot be greater than 255 or less than 0." << endl;
return 0;
}
////////////////////////////////////////////////////////////////////
// Calculates the binary value of the input.
// Works by looping through and taking away the already stored
// binary numbers.
////////////////////////////////////////////////////////////////////
if (number % 2) {
result = 1;
numCopy--;
}
while (numCopy != 0) {
if(numCopy / 128) {
result = result + 10000000;
numCopy = numCopy - 128;
}
else if(numCopy / 64) {
result = result + 1000000;
numCopy = numCopy - 64;
}
else if(numCopy / 32) {
result = result + 100000;
numCopy = numCopy - 32;
}
else if(numCopy / 16) {
result = result + 10000;
numCopy = numCopy - 16;
}
else if(numCopy / 8) {
result = result + 1000;
numCopy = numCopy - 8;
}
else if(numCopy / 4) {
result = result + 100;
numCopy = numCopy - 4;
}
else if(numCopy / 2) {
result = result + 10;
numCopy = numCopy - 2;
}
else {
cout << "ERROR: Invalid number." << endl;
return 0;
}
}
////////////////////////////////////////////////////////////////////
// Output
////////////////////////////////////////////////////////////////////
return result;
}
Here is a simpler version of what I'm trying to do...
But even THIS doesn't work. Result should output: 128, 64, 32, 16, 8, 4, 2, 1. But it skips 64, 16, 4, and 1. Any suggestions?Code:#include <iostream>
using namespace std;
int main() {
int val = 255;
int result = 0;
const unsigned int mask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for (int nBit = 0; nBit < 8; nBit++) {
result = ((val & mask[nBit]) >> nBit);
cout << result << endl;
}
return(0);
}
Actual output:
Code:128
32
8
2
0
0
0
So you're converting a decimal number into a decimal representation of its binary number... and then trying to use bitmasks to print the binary number?Quote:
Here is another part of the code you might want to look at (just in case it's got something wrong with it -- but I don't think it does) This is the part where it converts a decimal number to binary.
That won't work, and I don't think it's what you want. Try cutting out the binaryConv() function altogether, and see if that works better for you.
[edit]
I'm not sure if I was clear enough. The number is already stored in memory in binary format, so there is no need for any conversion.
Code://------------------------ERRORS?
for(int i=0; i < (imageWidth * imageLength); i++)
{
int binValue = binaryConv(buf[i]);
for(int j = 0; j < 8; j++)
{
// this should be buf[i], NOT binValue....
// if(binValue & bit[j])
if(buf[i] & bit[j])
{
cout << 1;
}else{
cout << 0;
}
}
cout << " " << binValue << endl;
}
//-------------------------
[/edit]
This should work, without the shift right.
Code:#include <iostream>
using namespace std;
int main() {
int val = 255;
int result = 0;
const unsigned int mask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for (int nBit = 0; nBit < 8; nBit++) {
result = (val & mask[nBit]);
cout << result << endl;
}
return(0);
}
how about something like:
Code:int binconvert(int num)
{
int x=0;
for (int i=0;i<8;i++)
{
if (num&mask[i])
x+=mask2[i]; //where mask2 holds 10000000,1000000,...
}
return x;
}
Thanks everyone, with your help I figured it out. Now it works, the binary is converted properly. Now I just have to figure out how to get it to read up to a non-multiple of 8 ... Say I have a 10x10 image. What's the best way to have it read all 100 bits, but not go over (or under)?
Newest code:
Code:int binValue = 0;
int count = 0;
for(int i=0; i < ((imageWidth * imageLength) / 8); i++)
{
for(int j = 0; j <= 7; j++)
{
binValue = (buf[i] & bit[j]);
if(binValue == 0) cout << 0;
if(j == 0 && binValue == 128){
cout << 1;
}
if(j == 1 && binValue == 64){
cout << 1;
}
if(j == 2 && binValue == 32){
cout << 1;
}
if(j == 3 && binValue == 16){
cout << 1;
}
if(j == 4 && binValue == 8){
cout << 1;
}
if(j == 5 && binValue == 4){
cout << 1;
}
if(j == 6 && binValue == 2){
cout << 1;
}
if(j == 7 && binValue == 1){
cout << 1;
}
count++;
if((count % imageWidth) == 1 && count != 1 || imageWidth == 1) cout << endl;
}
}
}
I'm curious as to why you are using "bit[j]" when all it does is increase execution time and required ram space. Why not calculate this array in realtime as you need it ?
Eg.
Instead of this:
do this:Code:for(int j = 0; j <= 7; j++)
{
binValue = (buf[i] & bit[j]);
I wonder also about your large if statement, isn't the following easier?Code:for(int j = 0; j <= 7; j++)
{
binValue = (buf[i] & (1<<j));
Code:for(int j = 0; j <= 7; j++)
{
binValue = (buf[i] & (1<<j));
if (binValue) cout << 1; else cout << 0;
}
I actually did change it to this...
Can someone try this and see if they are getting the correct values?Code:const unsigned int bit[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int binValue = 0;
int count = 0;
int j = 0;
for(int k=0; k < imageLength; k++)
{
for(int i=0; i < imageWidth; i++)
{
if(j > 7) j = 0;
binValue = (buf[i] & bit[j]) >> j;
cout << binValue;
j++;
}
cout << endl;
}
The next step (if this works) is to get the output to reverse what it is right now... any suggestions on the fastest way to do that?
I've not tried it, but it seems like it would work, even if it's a little complicated.
If you insist on using your array, why not just use a simple comparison rather than a shift? It would make your code easier to read...
Code:const unsigned int bit[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int binValue = 0;
int count = 0;
int j = 0;
for(int k=0; k < imageLength; k++)
{
for(int i=0; i < imageWidth; i++)
{
if(j > 7) j = 0;
binValue = ((buf[i] & bit[j]) ? 1 : 0 );
cout << binValue;
j++;
}
cout << endl;
}
ok, I made that change... but I'm trying to isolate the problem of why my program won't work (properly) ... Do you think this is all working properly? This part, at least.
Well, from looking at it, your program checks the 7th bit of the first byte, and then the 6th bit of the second byte, 5th bit of the third byte/etc and so on - is this what it is supposed to do? If not, then you need to loop J to check every bit before moving onto the next byte.
To test for a single bit in a number:
Code:bool testBit( int number, int bitIndex)
{
return number & 1<<bitIndex;
}
Slight correction here on your code:Quote:
Originally posted by Sang-drax
To test for a single bit in a number:
Code:bool testBit( int number, int bitIndex)
{
return number & 1<<bitIndex;
}
return !!(number & 1 << bitIndex);
Without the double not statement, you are not actually returning a boolean value. The only way you would, would be if bitIndex was zero. Anything else does not return 1. It returns a power of two.
While it is true that it would work for an equality test, where anything non-zero is considered true, in your case, it is incorrect, because bool should only ever be one or zero.
This would fail:
if( testBit( 2, 1 ) == 1 )
Because "number & 2" would return two, not one.
Quzah.
I have added comments to show what I believe this does... Please correct me if I'm wrong. And if there's an easier/better/right way to do it.
(it says PHP but that's just so you can see the color and it's easier to read)
PHP Code:
int binValue = 0;
int j = 0;
for(int k=0; k < imageLength; k++) //loops to the start of every line of pixels
{
for(int i=0; i < imageWidth; i++) //loops to each pixel in the line
{
if(j > 7) j = 0; //restarts the bit count
binValue = ((buf[i] & mask[j]) ? 1 : 0 ); //checks the bit if it's on or off
cout << binValue;
j++; //increments bit count
}
cout << endl;
}
I can tell what your code does without comments, and it still does exactly what I described above - checks exactly one bit in each byte. Why? Because "y" is incremented only after "i" has changed.
The program, as it stands, checks the 7th bit of the first byte, and then the 6th bit of the second byte, 5th bit of the third byte/etc and so on, like I said above before you ignored my post :p
It seems like the loop is not correct:
you would first get buf[0] & mask[0]Code:binValue = ((buf[i] & mask[j]) ? 1 : 0 );
but then it would be buf[1] & mask[1]
dont you want to compare every bit in the byte before moving on to the next one?
maybe add another loop:
Code:for(int i=0; i < imageWidth; i++)
{
for (int j; j < 7; j++)
{
binValue = ((buf[i] & mask[j]) ? 1 : 0 );
cout << binValue;
}
}
but I really don't understand what you are doing...
I think JaWib is right. Assuming you want to check all eight bits per byte, you need another loop. And if you want to print the most sigficicant bit first (instead of the least significant bit), just change the bit array (old code commented).
Code:const unsigned int bit[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int binValue, j;
int byte = 0;
for (int k=0; k < imageLength; k++)
{
for (int i=0; i < imageWidth; i++)
{
//if(j > 7) j = 0;
for (j=0; j<8; j++)
{
//binValue = ((buf[i] & bit[j]) ? 1 : 0 );
binValue = ((buf[byte] & bit[j]) ? 1 : 0 );
cout << binValue;
}
cout << " ";
byte++;
//j++;
}
cout << endl;
}
Is it possible to AND with decimals 1,2,4,8,16,32,64, etc? I don't care if it's not the standard way, but is it possible?Quote:
Originally posted by adrianxw
You should be using a bitmask not an integer, i.e. instead of 1 use 0x01, instead of 10 use 0x02, 100 - 0x04 1000 - 0x08 10000 - 0x10, 100000 - 0x20, 1000000 - 0x40 and 10000000 - 0x80.
I don't understand x & 0["@"]. Is "0" a system defined character array?
I still don't understand. Is Steve Summit saying that 5["abcdef"] will return 'f'? As if you've said "abcdef"[5]?
>>>
Is it possible to AND with decimals 1,2,4,8,16,32,64, etc? I don't care if it's not the standard way, but is it possible?
<<<
Yes of course, the point I was making is he was not using 1,2,4... he was using 1, 10, 100...
Point taken, adrian. That's interesting Salem, although I've never seen that method used in any code.
Thanks guys, for helping me... however... when I tried JawiB's code, it runs each one 7 times... which I don't want. it should run it once, checking through each one 7 times. here's the updated code...
Is my mask wrong? Or is something else wrong?PHP Code:
unsigned char mask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
int binValue = 0;
int j = 0;
int stride = (imageWidth + 7) / 8;
unsigned char* rowBuff, *pixByte;
for(int k=0; k < imageLength; k++)
{
rowBuff = buf + stride * k;
for(int i=0; i < imageWidth; i++)
{
pixByte = rowBuff + (i / 8);
cout << " -" << (int)*pixByte << "-" << endl;
if(j > 7) j = 0;
binValue = ((*pixByte & mask[j]) ? 1 : 0 );
cout << binValue;
j++;
}
cout << endl;
}
By the way... I am getting strange results for (int)*pixByte ... sometimes I will get something like one of these: 31, 13, 30, or 63. The rest are 0s and 255s (which they should be). Anyone have an explaination?
Can anyone help me?
Don't bump.
Quote:
Originally posted by quzah
Slight correction here on your code:
return !!(number & 1 << bitIndex);
Without the double not statement, you are not actually returning a boolean value. The only way you would, would be if bitIndex was zero. Anything else does not return 1. It returns a power of two.
While it is true that it would work for an equality test, where anything non-zero is considered true, in your case, it is incorrect, because bool should only ever be one or zero.
This would fail:
if( testBit( 2, 1 ) == 1 )
Because "number & 2" would return two, not one.
Quzah.
Wait a moment, I think that would be buggy compiler behavior. bool is a built-in type in C++ that can only have the states true (1) and false (0).
That means if I do:
VC++ will issue a warning (truncation cast, possible data loss) but will compile and output "1". That's because the 3 gets converted to boolean true and then to integer again, resulting in 1.Code:bool retBool()
{
return 3;
}
int main()
{
cout << (int)retBool() << endl;
return 0;
}
That's VC++7.1, about the most standards compliant compiler out there.
For all of you who were helping me with it, thanks... I figured it out!