"Double" variables in arduino

floats and doubles are not the same

Indeed, generally speaking, they are not.

But...

The statement that I made about them being the same directly followed the statement that said I had tested them within the Arduino environment and found the results to be the same.

So, maybe I misspoke. Maybe I should have emphasized that, in general, doubles and floats are not necessarily the same, but with the Arduino (using avr-gcc/avr-libc) they are treated the same. See Footnote.

In fact, maybe I could have just given a link to the Arduino reference, which states:

"The double [i]implementation[/i] on the Arduino is currently exactly the same as the float"

(Emphasis added)

However...

Note that this is not an Arduino thing. It's an avr-gcc/avr-libc thing. See Frequently Asked Questions, where it says

"float and double are 32 bits (this is the only supported floating point format)"

In fact I always like to test these things for myself. When I start using a new compiler I always test sizes of variables. Sometimes ints are 16-bits and longs are 32-bits. Sometimes ints are 32-bits and longs are 32-bits. Sometimes ints are 32-bits and longs are 64-bits. Sometimes floats are 32-bits and doubles are 32-bits. Sometimes floats are 32-bits and doubles are 64-bits. There may be other possibilities and combinations. (Also, I always test sizes of pointers and I always test endianness. Sometimes it makes a difference, especially when debugging other people's code.)

Anyhow...

In fact with avr-gcc, the code created for floats is exactly the same as the code that is created for doubles. Exactly. I mean, with avr-gcc/avr-libc you can declare something to be a double, but it generates the same code as if you had declared it to be a float.

You can check my results on any system that uses avr-gcc and avr-libc by actually inspecting the bytes:

Here's an Arduino sketch:

// Sketch TestDouble
//
// Prints bytes of a float
// Prints bytes of a double
//
// For avr-gcc and an ATMega328p, the bytes are exactly the same.
//
// Conclusion: The only floating point data type that is
// supported is 32-bits.
//
// You can declare stuff to be doubles if it suits your fancy,
// but there is no difference in the code from what it would
// have been if you had declared them to be floats.
//
//  davekw7x
//
void setup()
{
    Serial.begin(9600);
}

typedef union _chdoub {
    double x;
    unsigned char ch[sizeof(double)];
} chdoub;

typedef union _chfloat {
    float x;
    unsigned char ch[sizeof(float)];
} chfloat;

void loop()
{
    chdoub chd;
    chfloat chf;
    char buffer[100];
    char buf[100];
    double xx = 3.14159265358979323846;
    float yy  = 3.14159265358979323846;
    int i;
    chd.x = xx;
    chf.x = yy;
    
    
    sprintf(buffer, "sizeof(float) = %d, sizeof(double) = %d\n",
    sizeof(float), sizeof(double));
    Serial.print(buffer);
    sprintf(buffer, "chd: 3.14159265358979323846 --- ");
    for (i = 0; i < sizeof(double); i++) {
        sprintf(buf, "0x%02x ", chd.ch[i]);
        strcat(buffer, buf);
    }
    strcat(buffer, "\n");
    Serial.print(buffer);
    
    sprintf(buffer, "chf: 3.14159265358979323846 --- ");
    for (i = 0; i < sizeof(float); i++) {
        sprintf(buf, "0x%02x ", chf.ch[i]);
        strcat(buffer, buf);
    }
    strcat(buffer, "\n");
    Serial.print(buffer);
    
    delay(5000);
}

Output:


sizeof(float) = 4, sizeof(double) = 4
chd: 3.14159265358979323846 --- 0xdb 0x0f 0x49 0x40 
chf: 3.14159265358979323846 --- 0xdb 0x0f 0x49 0x40

---

Regards,

Dave

Footnote: Make a C (or C++) program on your workstation (Windows or Linux). Instead of loop(), just use that code as your main(). (Of course use printf statements instead of the Serial.print stuff.)

Compile with any more-or-less standard C or C++ compiler (GNU, Microsoft, Borland, ...)

You will (probably) see something like
Output:


sizeof(float) = 4, sizeof(double) = 8

chd: 3.14159265358979323846 --- 0x18 0x2d 0x44 0x54 0xfb 0x21 0x09 0x40 
chf: 3.14159265358979323846 --- 0xdb 0x0f 0x49 0x40