Go Down

Topic: Where can I find Arduino Mega dtostrf()'s implementation? (Read 314 times) previous topic - next topic

alirezasafdari

Hi

I am supper tired while writing this. I think I have found an issue with dtostrf but at this point I can not relay on my brain. I think it has problems with big numbers. But that is probably for later.

At this stage I looked for dtosrtf and I found in stdlib.h, however I cannot find the implementation file.

I am going to provide the code related to dtostrf if any of you is more familiar with the terms used in the description (ex. ingroup avr_stdlib)

Code: [Select]
/**
   \ingroup avr_stdlib
   The dtostrf() function converts the double value passed in \c val into
   an ASCII representationthat will be stored under \c s.  The caller
   is responsible for providing sufficient storage in \c s.

   Conversion is done in the format \c "[-]d.ddd".  The minimum field
   width of the output string (including the possible \c '.' and the possible
   sign for negative values) is given in \c width, and \c prec determines
   the number of digits after the decimal sign. \c width is signed value,
   negative for left adjustment.

   The dtostrf() function returns the pointer to the converted string \c s.
*/
extern char *dtostrf(double __val, signed char __width,
                     unsigned char __prec, char *__s);

/**
   \ingroup avr_stdlib
    Successful termination for exit(); evaluates to 0.
*/
#define EXIT_SUCCESS 0

/**
   \ingroup avr_stdlib
    Unsuccessful termination for exit(); evaluates to a non-zero value.
*/
#define EXIT_FAILURE 1
CRAE TECH

gfvalvo

Maybe it only exists in the Arduino installation in a compile library object file?

alirezasafdari

@gfvalvo

Ok, I am not really sure what that means. In case that is the case, is there anyway to see the implementation?
CRAE TECH

Delta_G

What's the issue you think you've found.  That function has been around long enough and been tested enough times to cast serious doubt on your assertion.  Most folks that think they've found a bug in the core really just have a bug in their thinking. 
If at first you don't succeed, up - home - sudo - enter.

gfvalvo

@gfvalvo

Ok, I am not really sure what that means. In case that is the case, is there anyway to see the implementation?
Object code is the output from the compiler and input to the linker.

When the statement
Code: [Select]
extern char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s);
is included in your code it tells the compiler: "here's the function's prototype, don't worry about the code that implements it, the linker will find it"

I agree with Delta_G, my money is on pilot error.

alirezasafdari

@Delta_G
This is the actual code I wrote to test. I noticed an unusual behavior in a bigger code that is why I broke it down to pieces to see what is up. I checked everything else, there are issues but I was more concerned to make sure I understand how dtostrf works. Something that I find kind of unusual (off topic) is that it does not have a way to say if it has failed. It returns a pointer to the buffer which I have not checked but cannot understand how that helps. Anyways, this a code to show why I am interested to see the implementation.

Code: [Select]
numberInput = 99999999999999999999999999999999999;
 dtostrf(numberInput, 50, 1, buf);
 Serial.write(buf, 50);
 Serial.println();

 numberInput = 999999999999999999999999999999999999;
 dtostrf(numberInput, 50, 1, buf);
 Serial.write(buf, 50);
 Serial.println();


This code produce the following result:
Code: [Select]
3136634000000000000.0
-5527149300000000000.0



Based on this
https://www.h-schmidt.net/FloatConverter/IEEE754.html
The value represented should be different unless another type of float has been use, or the dtostrf works differently on this one. I did not do a hand calculation but I did use this website as a reference to make sure there is no issue with the variable type and its limitation.
CRAE TECH

gfvalvo

The value represented should be different unless another type of float has been use, or the dtostrf works differently on this one. I did not do a hand calculation but I did use this website as a reference to make sure there is no issue with the variable type and its limitation.
We don't know the variable types since you didn't post complete code.

sterretje

If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

alirezasafdari

Code: [Select]
volatile float numberInput = -3, zero = 0;
char buf[50];

void setup()
{
Serial.begin(115200);
Serial.println("begin");
}

void loop()
{
numberInput = 99999999999999999999999999999999999;
dtostrf(numberInput, 50, 1, buf);
Serial.write(buf, 50);
Serial.println();

numberInput = 999999999999999999999999999999999999;
dtostrf(numberInput, 50, 1, buf);
Serial.write(buf, 50);
Serial.println();

while(1);
}
CRAE TECH

sterretje

Your buf is too small. No space for terminating nul character.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

cattledog

Code: [Select]
numberInput = 99999999999999999999999999999999999;
numberInput = 999999999999999999999999999999999999;


The two values for number input are not the same. There is one extra 9 in the second number input.

Code: [Select]
volatile float numberInput = -3, zero = 0;
char buf[50];

void setup()
{
  Serial.begin(115200);
  Serial.println("begin");
}

void loop()
{
  numberInput = 99999999999999999999999999999999999;
  dtostrf(numberInput, 50, 1, buf);
  Serial.write(buf, 50);
  Serial.println();

  numberInput = 99999999999999999999999999999999999;//9;
  dtostrf(numberInput, 50, 1, buf);
  Serial.write(buf, 50);
  Serial.println();
 
  while(1);
}

oqibidipo

Code: [Select]
numberInput = 99999999999999999999999999999999999;
numberInput = 999999999999999999999999999999999999;


Those are integer constants and are too large for any supported integer type. The result is the lowest 64 bits of the value.

Append .0 the the values to make them float constants.
(Well, actually double constants... .0f for float.)

alirezasafdari

#12
Nov 08, 2017, 05:00 am Last Edit: Nov 08, 2017, 05:24 am by alirezasafdari
Just to help the future readers, the correct answer is given by oqibidipo. Now, I understand why they always say, we should put the '.0' at the end of the float/double value. Thank you very much oqibidipo.

The values are not the same with no doubt but the printed values were way off.

The buffer is twice larger than it should be.
CRAE TECH

westfw


alirezasafdari

Thank you westfw for pointing out the source for implementation of dtostrf
CRAE TECH

Go Up