Strange float behaviour on Arduino Mega

With 32-bit floats, that value and the ones before and after (by decrementing or incrementing the Significand) are approximately

  • 1234.567749 before
  • 1234.567871
  • 1234.567993 after
  • 1234.568115 after that

The value is incrementing by one at the 8th digit, but then skips .5680. (If rounding instead of truncating, there's no .5678) So almost eight significant digits, but really only seven.

The difference is with the String constructor. On AVR, try

void setup() {
  Serial.begin(115200);
  float myFloat = 0.090650305151939f;
  Serial.println(sizeof(myFloat));
  Serial.println(String(myFloat, 15));
  Serial.println(myFloat, 15);
  Serial.println(String(9065.03f / 100000, 15));
  Serial.println(9065.03f / 100000, 15);
}


void loop() {}

With Wokwi I get

4
0.090650305000000
0.090650310516357
0.090650305000000
0.090650310516357

The same code with ESP32 all prints the original best-approximate

0.090650305151939

The "not-rounded" on AVR is not the same. It's closer to the number that comes after

  • 0.0906502977 before
  • 0.09065030515
  • 0.0906503126 after

but not quite. More on this later, but at least the difference is past the significant digits. The String constructor on both boards -- AVR

String::String(float value, unsigned char decimalPlaces)
{
	init();
	char buf[33];
	*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}

and ESP32

String::String(float value, unsigned int decimalPlaces) {
  init();
  char *buf = (char *)malloc(decimalPlaces + 42);
  if (buf) {
    *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
    free(buf);
  } else {
    *this = "nan";
    log_e("No enough memory for the operation.");
  }
}

(those are big buffers, but check out the one for double on ESP32) -- both use dtostrf; on ESP32 versus on AVR, where apparently it calls dtoa_prf. Quite different between those two and also Print::print, which is the same code on AVR and ESP32. But that code uses double, which is only 32-bit on AVR, so the results deviate.

1 Like