Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: float and double

  1. #1
    Member
    Join Date
    Oct 2015
    Location
    Okanagan, BC, Canada
    Posts
    59

    float and double

    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

    Click image for larger version. 

Name:	Screenshot 2015-10-30 15.02.30.png 
Views:	1274 
Size:	52.1 KB 
ID:	5399

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,036
    Basically GCC is now told to make floating point constants float by default instead of double. For more information, consult this thread: https://forum.pjrc.com/threads/31116...oint-constants

  3. #3
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,289
    Yes, that was a chage to make Teensyduino more compatible to Arduino, where double has the same precision as float

    You need to write them like
    double x = 0.123456789L (<- note the "L") now

  4. #4
    Member
    Join Date
    Oct 2015
    Location
    Okanagan, BC, Canada
    Posts
    59
    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.

  5. #5
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,289
    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 by Frank B; 10-30-2015 at 11:11 PM.

  6. #6
    Member
    Join Date
    Oct 2015
    Location
    Okanagan, BC, Canada
    Posts
    59
    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.

  7. #7
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,289
    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 ?

  8. #8
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    706
    Is this useful? An example of printing many significant digits from Teensy (using a custom function):
    https://forum.pjrc.com/threads/21479...ll=1#post27217

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,289
    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:rintFloat(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 by Frank B; 10-30-2015 at 11:36 PM.

  10. #10
    Member
    Join Date
    Oct 2015
    Location
    Okanagan, BC, Canada
    Posts
    59
    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.

  11. #11
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,110
    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.

  12. #12
    Member
    Join Date
    Oct 2015
    Location
    Okanagan, BC, Canada
    Posts
    59
    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!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •