I think I found a bug, need sanity confirmation

Hello,

It’s been a while since I’ve done any C programming, so I wanted to confirm that this is unexpected behavior. I recently purchased an Arduino starter kit from Sparkfun that includes an Arduino Uno. I’m using version 0022 of the software. I’m trying to make a binary counter with some LEDs (my second project) and have encountered some strange behavior with C typecasting. Here is the code below, followed by the serial monitor output.

#include "math.h"

#define NUM_OF(x) (sizeof (x) / sizeof *(x))

int pinArray[]  = {9, 8, 7, 6, 5, 4, 3, 2};
int pinCount    = NUM_OF(pinArray);

void setup() {
    Serial.begin(9600);
    for (int i = 0; i < pinCount; i++) {
        pinMode(pinArray[i], OUTPUT);
        digitalWrite(pinArray[i], LOW);
    }
}

void loop() {
    int x = 0;
    char buffer[80] = "";
    while (x <= 7) {
        Serial.print(x);
        Serial.print("-> ");
        for (int i = 0; i < pinCount; i++) {
            float n = pow(2, i);
            int N = int(n);
            int b = x & N;
            
            // sprintf isn't handling floats well, sorry for the mess below.
            Serial.print(b);
            Serial.print(" (");
            Serial.print(n);
            Serial.print(", ");
            Serial.print(N);
            Serial.print(")  ");
            
            if ((x & int(pow(2, i))) > 0) {
                digitalWrite(pinArray[i], HIGH);
            } else {
                digitalWrite(pinArray[i], LOW);
            }
        }
        Serial.println(" ");
        x++;
        delay(2000);
    }
}
0-> 0 (1.00, 1)  0 (2.00, 2)  0 (4.00, 3)  0 (8.00, 7)  0 (16.00, 15)  0 (32.00, 31)  0 (64.00, 63)  0 (128.00, 127)   
1-> 1 (1.00, 1)  0 (2.00, 2)  1 (4.00, 3)  1 (8.00, 7)  1 (16.00, 15)  1 (32.00, 31)  1 (64.00, 63)  1 (128.00, 127)   
2-> 0 (1.00, 1)  2 (2.00, 2)  2 (4.00, 3)  2 (8.00, 7)  2 (16.00, 15)  2 (32.00, 31)  2 (64.00, 63)  2 (128.00, 127)   
3-> 1 (1.00, 1)  2 (2.00, 2)  3 (4.00, 3)  3 (8.00, 7)  3 (16.00, 15)  3 (32.00, 31)  3 (64.00, 63)  3 (128.00, 127)   
4-> 0 (1.00, 1)  0 (2.00, 2)  0 (4.00, 3)  4 (8.00, 7)  4 (16.00, 15)  4 (32.00, 31)  4 (64.00, 63)  4 (128.00, 127)   
5-> 1 (1.00, 1)  0 (2.00, 2)  1 (4.00, 3)  5 (8.00, 7)  5 (16.00, 15)  5 (32.00, 31)  5 (64.00, 63)  5 (128.00, 127)   
6-> 0 (1.00, 1)  2 (2.00, 2)  2 (4.00, 3)  6 (8.00, 7)  6 (16.00, 15)  6 (32.00, 31)  6 (64.00, 63)  6 (128.00, 127)   
7-> 1 (1.00, 1)  2 (2.00, 2)  3 (4.00, 3)  7 (8.00, 7)  7 (16.00, 15)  7 (32.00, 31)  7 (64.00, 63)  7 (128.00, 127)

Notice that the typecasting of a float to an int is producing int-1. Am I doing something wrong? Is this known behavior?

Thanks.

If you print out the float version of the number you will probably see 1.999+. When rounded to 2 decimal places for display it comes out as 2.00. When truncated to an integer it comes out as 1.

i<<i == 2^i Use that if you are working with integer powers of 2.

If you want to see the 'power' of rounding in floating point, change this:

int N = int(n);

to this:

int N = int(n+0.5);

This should put those values over the top.

Please note - this is NOT a way to fix the code - as john pointed out, you should work in integer math here - your results will be more accurate, and your code much faster.

            // sprintf isn't handling floats well, sorry for the mess below.

Change well to "at all" and the comment will be correct.