tags:

views:

176

answers:

5

I am writing code that compares 2 bytes which represent integers. I want to see if byte R is with +-10 of G. The problem I am having with the code is with the comparison in the if-statment near the end. The bytes never come out as being out of range, even when they should. I am sure the problem comes from how I am adding/subtracting the error_range, but I don't know any other way to do it.

I first considered converting the bytes into integers but I cannot find any help with that online. If that would work better than what I am doing here, please tell me how to do it.

Any help is appreciated!

const char ERROR_RANGE = 0x1010; //warning: overflow in implicit constant conversion
char R, G; /2 separate bytes
char buffer; //enough space for 1 byte

image = fopen(fileName,"r"); //open file

fread(&buffer, 1, 1, image); //read 1 byte  
memcpy (&R,&buffer,1); //store it as R

fread(&buffer, 1, 1, image); //read 1 byte   
memcpy (&G,&buffer,1); //store it as G

fclose(image);

if((R >= (G + ERROR_RANGE)) && (R <= (G - ERROR_RANGE)))
{
    printf("Outside of range!\n");
}

Thanks.

+11  A: 

Your problem is because your test says:

if (R is greater than or equal to G + ERROR) AND (R is less than or equal to G - ERROR)

it can't be both.

Replace the && with || in the first instance.

A better test would be:

if (the difference of R and G is greater than ERROR)

which translates to:

if (abs(R - G) > ERROR_RANGE)
{
    printf("Error");
}
ChrisF
WOW thanks for catching that. I definitely meant or! And thanks for the suggestion about subtracting them!
KMM
@KMM - If I'm having trouble with compound if statements I often write them out in English or pseudo code, I find it easier to spot when I've got my ANDs and ORs the wrong way round or missed out a NOT
ChrisF
If you prefer writing them out in English, that's what iso646.h is for.
Steve Jessop
@Steve Jessop - I meant as in my answer as it brings out the meaning of the test, but I take your point.
ChrisF
Steve Jessop
+6  A: 

First problem is that you're using &&, not ||. R isn't going to be both too high and too low.

Second, are you sure that R and G will be within reasonable bounds? If char on your system is unsigned, then G - ERROR_RANGE may well be a large number if G is small, not a small one. You're probably best off with something like if (abs(R - G) <= ERROR_RANGE).

David Thornley
Since R and G are both single bytes, then they're going to be well within the reasonable range supported by 'int' (and the values are promoted to 'int' before the comparisons or computations occur, of course - normal promotions).
Jonathan Leffler
+1 for beating me to it...
Jerry Coffin
@Jonathan: Thanks for reminding me. However, if char is unsigned on this particular implementation (and IIRC the Standard allows it to be either), doesn't it promote to unsigned int? In that case, we've still got the problem.
David Thornley
@David: what are the worst cases we can have? 'signed char' of -128 and +127, promoted to int? Or 'unsigned char' 0 and 255, both promoted to int (no need to go to unsigned int); the difference in each case is ±255, which is readily handled by 'int'. I don't think there's a problem, unless the values 0 and 255 are 1 apart because the values are meant to be circular.
Jonathan Leffler
@Jonathan: My fault. Thank you very much. I misremembered the promotion rules.
David Thornley
+2  A: 

Is there some reason you couldn't use something like:

if (abs(R-G) > ERROR_RANGE)
    // ...
Jerry Coffin
+1  A: 

Here's my stab at it, UNTESTED:

unsigned char buffer[2];
int r, g, diff;

image = fopen(fileName, "r");
fread(&buffer, 2, 1, image);

r = buffer[0];
g = buffer[1];
dif = r - g;

if (abs(dif) > 10) { printf... }

It uses the abs function to make the difference always positive... easier to compare that way. A slight performance improvement from reading both of the first 2 bytes in one go. Assigning the (unsigned) chars to ints will make them easily comparable.

Carl Smotricz
+3  A: 

Aside from what's already been pointed out...

The value 0x1010 is too large to fit in a byte, and two bytes can never be different by more than 255 (0xff). Did you mean 1010 binary (== 10 decimal == 0xA hex)?

Also, there's no need to read and copy, you can just read into your variables directly:

fread(&R, 1, 1, image); //read 1 byte  
fread(&G, 1, 1, image); //read 1 byte
Tim Sylvester
Yes I meant 10 in decimal. Thank you very very much.
KMM
+1 for guessing the binary vs hex confusion.
Jonathan Leffler