float and double

Status
Not open for further replies.

Skiddy

Well-known member
having only started with Teensy and C 3 to 4 weeks ago I am a noob. I also have no clue how to use this forum properly, so please bear with me.

When I am declaring some numbers either as float or double and then print them out, I get different results. I understand that a float will provide less precision than a double but curiously neither one of them matches the input after a number of digits.

#define ARM_MATH_CM4
#include <arm_math.h>

// Calibration parameter s
float CAL1_PARAM_A = 2.30877461071517E+05;
float CAL1_PARAM_B = -1.96685260458407E-01;
float CAL1_PARAM_C = -6.56726954265664E-06;
float CAL1_PARAM_D = 1.42999616118481E-11;
double CAL2_PARAM_A = 2.30877461071517E+05;
double CAL2_PARAM_B = -1.96685260458407E-01;
double CAL2_PARAM_C = -6.56726954265664E-06;
double CAL2_PARAM_D = 1.42999616118481E-11;



void setup() {
// put your setup code here, to run once:
Serial.begin(115200); // Set up serial port.
delay(5000);
}

void loop() {
// put your main code here, to run repeatedly:
Serial.print(CAL1_PARAM_A * 1,7);
Serial.print("\t");
Serial.print(CAL1_PARAM_B * 1000000,7);
Serial.print("\t");
Serial.print(CAL1_PARAM_C * 10000000000,7);
Serial.print("\t");
Serial.print(CAL1_PARAM_D * 100000000,7);
Serial.println("\t");
Serial.print(CAL2_PARAM_A * 1,7);
Serial.print("\t");
Serial.print(CAL2_PARAM_B * 1000000,7);
Serial.print("\t");
Serial.print(CAL2_PARAM_C * 10000000000,7);
Serial.print("\t");
Serial.print(CAL2_PARAM_D * 100000000,7);
Serial.println("\t");
Serial.println();

delay(1000);
}

and here is the display

Screenshot 2015-10-30 15.02.30.png
 
Yes, that was a chage to make Teensyduino more compatible to Arduino, where double has the same precision as float:mad:

You need to write them like
double x = 0.123456789L (<- note the "L") now
 
Vielen Dank Frank, that did it. The numbers are now more precise. However this one

double CAL2_PARAM_D = 1.42999616118481E-11L;

or written like this:

const double CAL2_PARAM_D = 1.42999616118481E-11L;

still only show 0.0014300 I guess that's where even double ends.
 
hmm....did you try a higer number than "7" in the print() statement ?
Double precision (double) gives you 52 bits of significant, 11 bits of exponent, and 1 sign bit.

Edit: okay, it prints 0.0014299 for me..
 
Last edited:
I have not been able to figure out how to get more than 7 digits at the serial output, which is why I used the multipliers. Putting Serial.print(CAL2_PARAM_D, 5) gains me 5 decimals and Serial.print(CAL2_PARAM_D, 7) prints 7, which all makes sense but Serial.print(CAL2_PARAM_D, 12) still only shows 7 decimals. I also tried multiplying with less or more decades but no joy - always 143 only.

Even with only the 7 displayed decimals it should then read 0.0014299 instead of rounding it up.
 
Hm, it prints 0.0014299 for me.
That's interesting.. i don't know why it rounds up for you.
Which Teensyduino-Version do you use ?
 
Ha, if found the reason for 7 digits.
Its in "print.cpp". The internal buffer is only 8 Bytes.
Don't know why.

If you want to "cheat" you could edit "Print.cpp" and change the line
uint8_t n, buf[8], count=1;
inside size_t Print::printFloat(double number, uint8_t digits)
to (for example)
uint8_t n, buf[16], count=1;

then, it prints 0.001429996161184 (just tried)


Edit: i opened a pull-request @ github
 
Last edited:
I was not able to find the file in my Mac. I looked in the Contents folder from Arduino.app but may very well have overlooked it - so many files.
 
Please keep in mind Serial.print() only accepts 32 bit float.

To see the full accuracy, use Serial.printf(). Tools > CPU Speed has to be set to one of the optimize options (which is the default). If you change to reduce code size, printf() becomes a size optimized version which doesn't support any floats.
 
Thanks all, great stuff.

After getting an error message (no such USB call or something similar) during compile, when I entered Serial.printf(), I was able to find the Print.cpp file from the error message provided. Changing the buffer, as Frank explained, to

uint8_t n, buf[8], count=1;
inside size_t Print:rintFloat(double number, uint8_t digits)
to (for example)
uint8_t n, buf[16], count=1;

gained some more insight, so I then changed it to

uint8_t n, buf[8], count=1;
inside size_t Print:rintFloat(double number, uint8_t digits)
to (for example)
uint8_t n, buf[32], count=1;

and now printing from this double CAL1_PARAM_D = 1.42999616118481E-11L; with Serial.print(CAL1_PARAM_D,25); results in this: 0.0000000000142999616118481

Yeah!
 
Status
Not open for further replies.
Back
Top