Using double precision numbers in serial Teensy 3.2 and 4.0

Status
Not open for further replies.

JakeNBake

Member
Hello,

I'm trying to send some double precision values over serial to a teensy/arduino and store it in EEPROM then read it back over serial. During my testing it seems that only float precision can be displayed, does this mean that the teensy cannot store double (64 bit floats) values in its EEPROM (I am aware that the arduino can only handle 32 bit floats)? Or is this instead a flaw with the String() function?

Code:
void setup() {
  Serial.begin(9600);
  
}


void loop() {
  double number = 1.000001;
  double number2 = 1.0000005;
  
  Serial.println(String(number+ 2*number2,20));  
}

The output for each is as follows:

Code:
Arduino Uno
16:24:23.349 -> 3.00000190000000000000

Teensy 4.0
3.00000190734863281250

Many thanks
 
Arduino String and Serial.println only support 32 bit floats.

To print 64 bit double, use Serial.printf(). To convert to a string, use snprintf().

Code:
void setup() {
  Serial.begin(9600);
}

void loop() {
  double number =  1.0000010;
  double number2 = 1.0000005;
  Serial.printf("%lf\n", number+ 2*number2); 
}
 
You may know this, or perhaps you don't.

On the Teensy 3.2, 3.5, 3.6, and LC, floating point constants are single precision rather than double precision. On the Teensy 4.0 and 4.1, constants are double precision.

If you need a double constant to full precision on the Teensy 3.x/LC, you would need to specify it as a 'long double' constant and convert that to 'double':

Code:
  double x = (double) 3.1415926535L;

The reason for this is the M4 chips used in the Teensy 3.x series has an optional floating point unit (Teensy 3.5 and 3.6 use the FPU, Teensy 3.2 does not have a FPU). However, the floating point unit only does single precision arithmetic. I believe Paul used the GCC option to treat constants as single precision so that having a constant in an expression would not convert the whole expression to double precision which on the 3.5/3.6 would have to be emulated, instead of being done in hardware.

The Teensy 4.0 and 4.1 has full hardware support for both single and double precision, so constants are normally double precision (which is what the C/C++ standards specify).
 
As a follow up, is there a means of converting string to double other than 'string.toDouble' which gives me the error
Code:
'class String' has no member named 'toDouble'
 
is there a means of converting string to double other than 'string.toDouble'

snprintf() works, perhaps awkwardly if you like C++, but it's highly reliable ;)

Code:
void setup() {
  while (!Serial);
  double x = 1.000000123L;
  char buf[24];
  snprintf(buf, 24, "%.9lf", x);
  String s = buf;
  Serial.print(String("x is ") + s);
}

void loop() {
}

One minor caveat is it does not work if you set Tools > Optimize to "Smallest Code", because one of the space saving measures is a version of printf without floating point support. Only Teensy LC uses "Smallest Code" as its default.
 
Status
Not open for further replies.
Back
Top