Quantcast
Viewing all articles
Browse latest Browse all 39321

Minor bug in float to string conversion (no replies)

When I was using the web interface to lower the nozzle,
the reported nozzle height suddenly jumped up and down.

The problem:

A float with a zero on the right of the comma is converted incorrectly,
when the Z height is 0,09 it is presented as 0,9 in the web interface.

The problem location:

The "convert float to string" function in RepRapFirmware.cpp at line 293:
// Float to a string.

static long precision[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
char scratchString[STRING_LENGTH];

char* ftoa(char *a, float f, int prec)
{
  if(a == NULL)
    a = scratchString;
  char *ret = a;
  long whole = (long)f;
  if(!whole && f < 0.0)
  {
	  a[0] = '-';
	  a++;
  }
  snprintf(a, STRING_LENGTH, "%d", whole);
  while (*a != '\0') a++;
  *a++ = '.';
  long decimal = abs((long)((f - (float)whole) * precision[prec]));
  snprintf(a, STRING_LENGTH, "%d", decimal);
  return ret;
}
My translation:

The float value is split in two parts, left of the comma and right of the comma.
When both parts are combined with the desired precision, the %d kills zero's.

I have tried to fix this and my version of the code looks like this:
// Float to a string.

static const char *formatting[] = {"%d", "%d", "%02d","%03d","%04d","%05d","%06d","%07d","%08d"};
static long precision[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
char scratchString[STRING_LENGTH];

char* ftoa(char *a, float f, int prec)
{
  if(a == NULL)
    a = scratchString;
  char *ret = a;
  long whole = (long)f;
  if(!whole && f < 0.0)
  {
	  a[0] = '-';
	  a++;
  }
  snprintf(a, STRING_LENGTH, "%d", whole);
  while (*a != '\0') a++;
  *a++ = '.';
  long decimal = abs((long)((f - (float)whole) * precision[prec]));
  snprintf(a, STRING_LENGTH, formatting[prec], decimal);
  return ret;
}
The bug is a bit hard to trigger on the printer,
I have attached a source file to test it on a PC.
$ ./ftoa
Old ftoa with input 0.000 and precision 2: 0.0
Old ftoa with input 0.090 and precision 2: 0.9
Old ftoa with input 0.123 and precision 2: 0.12
New ftoa with input 0.000 and precision 2: 0.00
New ftoa with input 0.090 and precision 2: 0.09
New ftoa with input 0.123 and precision 2: 0.12
There are warnings about the %d in combination with 'long int',
the %d should probably be replaced by %ld for long int values.
$ gcc ftoa.c -o ftoa
ftoa.c:23:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Wformat]
ftoa.c:27:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Wformat]
ftoa.c:44:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Wformat]

Viewing all articles
Browse latest Browse all 39321

Trending Articles