Go Down

### Topic: printing double-precision floating point (Read 3106 times)previous topic - next topic

#### John Beale

##### Mar 13, 2013, 02:24 amLast Edit: Mar 13, 2013, 08:51 pm by John Beale Reason: 1
In case it is useful, here is an updated version of an older Arduino sketch to convert floating point numbers to a string in scientific notation for printing.
This one shows up to 16 decimal digits, so you can see the full accuracy of your double-precision float types. (Note, I have only tested it on a Teensy 3, not a Due.)
This fits into the category of "quick hack", it is not in any way optimized.

Sample output string:  3.1415926535897926 E+146

Try running this sketch on an older ATmega type Arduino, and you will see quite a difference in the range and precision of floating point values (because the original Arduinos set type double == type float).

Code: [Select]
`//// Test of function that builds a C-style "string" for a floating point// number in scientific notation.//// original by davekw7x December, 2010  // http://arduino.cc/forum/index.php/topic,46931.0.html// modified to use "double" and to run to smaller / larger values  March 12 2013 JPB//#define STEPS 330void setup(){    double f, fa;    int d;    char str[26];  // formated number as string        Serial.begin(115200);    delay(3000);    Serial.println("double precision floating point test");    f = 0.0;    // No "digits" argument means 2 digits    Serial.print("0.0 = ");Serial.println(double2s(f));Serial.println();        // Rounding with leading zeros in the fractional part    f = 10.3456;    Serial.print(f,4);Serial.print(" = ");Serial.println(double2s(f, 4));Serial.println();        /*       For loops 1 and 2, note that floating point       overflows result values of"INF"    */    f = PI;        Serial.println("Loop 1");    for (int i=1; i< STEPS; i++)    {        Serial.println(double2s(f, 16));        if (isinf(f)) break;                f *=1E1;    }    Serial.println();    f = -PI;    Serial.println("Loop 2");    for (int i=1; i< STEPS; i++)    {        Serial.println(double2s(f, 16));        if (isinf(f)) break;                f *=1E1;    }      Serial.println();    /*       For loops 3 and 4 note that floating point       underflows result in values that go to zero.    */    f = PI;    Serial.println("Loop 3");    for (int i=1; i< STEPS; i++)    {        Serial.println(double2s(f, 16));                if (f == 0.0) break;        f /= 1E1;    }    Serial.println();    f = -PI;    Serial.println("Loop 4");    for (int i=1; i< STEPS; i++)    {        Serial.println(double2s(f, 16));        if (f == 0.0) break;        f /= 1E1;    }    Serial.println();    /*       Loop 5 shows rounding as follows:        6: 1.999518 E+20        5: 1.99952 E+20        4: 1.9995 E+20        3: 2.000 E+20        2: 2.00 E+20        1: 2.0 E+20        0: 2 E+20    */    f = 1.999518e20;    Serial.println("Loop 5");    for (int i = 16; i >= 0; i--) {        Serial.print(i);Serial.print(": ");Serial.println(double2s(f, i));    }    Serial.println();        /*       Loop 6 shows rounding as follows:        6: 1.999496 E+20        5: 1.99950 E+20        4: 1.9995 E+20        3: 1.999 E+20        2: 2.00 E+20        1: 2.0 E+20        0: 2 E+2    */        f = 1.999496e20;    Serial.println("Loop 6");    for (int i = 16; i >= 0; i--) {        Serial.print(i);Serial.print(": ");Serial.println(double2s(f, i));    }        Serial.println();        Serial.println("NaN tests");    f = sqrt(-1);    Serial.print("sqrt(-1) = ");Serial.println(double2s(f, 3));    f = 0.0/0.0;    Serial.print("0.0/0.0 = ");Serial.println(double2s(f, 4));    f = INFINITY * 0;    Serial.print("INFINITY*0 = ");Serial.println(double2s(f, 5));Serial.println();        Serial.println("INFINITY tests");    f = 1.0/0;    Serial.print("1.0/0 = ");Serial.println(double2s(f, 1));    //printBytes(f);    f = -1.0/0;    Serial.print("1.0/-0 = ");Serial.println(double2s(f, 1));    //printBytes(f);    f = -1.0/0L;    Serial.print("1.0/0L = ");Serial.println(double2s(f, 2));        f = 1.0/0UL;    Serial.print("1.0/0UL = ");Serial.println(double2s(f, 3));        Serial.println();        // Note that tan(pi/2) may not result in INF due    // to limited precision.    //    f = tan(HALF_PI);    Serial.print("tan(");Serial.print(HALF_PI, 6);Serial.print(") = ");      Serial.println(double2s(f, 6));}void loop(){} // ====== double2s(): print out up to 16 digits of input double-precision value// This version enables double-precision for Teensy 3, etc. // by J.Beale March 2013// modified from original float2s() posted by davekw7x on December, 2010// http://arduino.cc/forum/index.php/topic,46931.0.htmlchar * double2s(double f){  return double2s(f, 2);}char * double2s(double f, unsigned int digits) {    int d;static char s[26];  // formated number as stringint index=0;  // handle sign  if (f < 0.0)  {    s[index++] = '-';    f = -f;  }  // handle infinite values  if (isinf(f))  {    strcpy(&s[index], "INF");    return s;  }  // handle Not a Number  if (isnan(f))  {    strcpy(&s[index], "NaN");    return s;  }  // max digits  if (digits > 16) digits = 16;  int exponent = int(log10(f));  double g = f / pow(10, exponent);  if ((g < 1.0) && (g != 0.0))        {    g *= 10;    exponent--;  }  if (exponent < -330) {  // lower limit of double-precision on Teensy 3    g = 0;    exponent = 0;  }  if (digits < 16) {  // display number rounded at last digit    g += 0.5 / pow(10,digits);  }    d = g;    sprintf(&s[index++],"%d",d);    if (digits > 0) sprintf(&s[index++],".");  for (int i=0;i<digits;i++) {      g = (g - d) * 10.0;  // shift one decimal place to the left      d = int(g);      sprintf(&s[index++],"%d",d);  }  sprintf(&s[index], " E%+d", exponent);  return s;    } // ===== end double2s()`

Go Up

Please enter a valid email to subscribe