# printf() with floats?

**URL:** <https://forum.arduino.cc/t/printf-with-floats/332051>\
**Category:** Programming\
**Created:** [August 28, 2015, 1:39am UTC](https://forum.arduino.cc/t/printf-with-floats/332051 "2015-08-28T01:39:28Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![HazardsMind](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/hazardsmind/32/215209_2.png) [@HazardsMind](https://forum.arduino.cc/u/HazardsMind)\
**Post date:** [August 28, 2015, 1:39am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/1 "2015-08-28T01:39:28Z")

</div>

I know the arduino core libraries (maybe even the "std" libraries) are not 100% perfect, thus the printf() function can't not handle float values. This is mainly due to va\_start, va\_list ... va\_end, not being the same as you would find if you use a real C/C++ compiler.

Well, I want to try adding float values to printf(), or at least give it a shot. However I can't not find where the Arduino software developers hid the actual \_\_builtin\_va\_start ... end functions. Are they somewhere in the library folders or is it part of the GCC files?

I made this sketch to convert a floating value to a string. I can also change it to the standard format of **"%4.2f"** down the line, that's not a problem. But where do I start?

```cpp
/*
  Had to make my own pow() function as the standard pow() has a return type of double,
  and for some reason type casting from a double to an int produces 1 less that of the value. 
  Ex. int(pow(10, 3)) returns 999 instead of 1000. (using IDE 1.6.0 on an UNO)
*/

void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(115200);

  char myB[10]; // buffer
  ftos(myB, 4, 3, 1234.567);
  Serial.println(myB);
}

void loop() {
  // put your main code here, to run repeatedly:
}

void ftos(char * buf, byte W, byte D, float data)
{
  long Wdata = data, tmp;
  float dec = data - long(data);
  
  // get the first whole number and convert it
  buf[0] = Wdata / Pow(10, W - 1) + '0';
  tmp = Wdata % Pow(10, W - 1);
  
  //now get the rest of the whole numbers
  for (byte i = 1; i < W; i++)
  {
    long factor = Pow(10, W - 1 - i);
    buf[i] = (tmp / factor) + '0';
    tmp %= factor;
  }
  
  buf[W] = '.'; // add the decimal point

  // now do the decimal numbers
  for (byte i = 0; i < D; i++)
  {
    dec *= 10; 
    buf[W + i + 1] = (long(dec) % 10) + '0';
  }
  // don't forget the NULL terminator
  buf[W + D + 1] = NULL; 
}

unsigned long Pow(long V, byte shift)
{
  unsigned long Val = 1;
  while(shift-- != 0)
    Val *= V;
  
  return Val;
}

```

---

<div class="post-metadata">

**Author:** ![econjack](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/econjack/32/1105255_2.png) [@econjack](https://forum.arduino.cc/u/econjack)\
**Post date:** [August 28, 2015, 1:53am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/2 "2015-08-28T01:53:32Z")

</div>

Maybe this will help:

[http://forum.arduino.cc/index.php?topic=344206.new#new](http://forum.arduino.cc/index.php?topic=344206.new#new)

especially post #3.

---

<div class="post-metadata">

**Author:** ![HazardsMind](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/hazardsmind/32/215209_2.png) [@HazardsMind](https://forum.arduino.cc/u/HazardsMind)\
**Post date:** [August 28, 2015, 1:59am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/3 "2015-08-28T01:59:39Z")

</div>

Ok, that is awesome. Thank you Econjack

---

<div class="post-metadata">

**Author:** ![krupski](https://avatars.discourse-cdn.com/v4/letter/k/c4cdca/32.png) [@krupski](https://forum.arduino.cc/u/krupski)\
**Post date:** [August 28, 2015, 4:53am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/4 "2015-08-28T04:53:11Z")

</div>

> HazardsMind:  
> I know the arduino core libraries (maybe even the "std" libraries) are not 100% perfect, thus the printf() function can't not handle float values. This is mainly due to va\_start, va\_list ... va\_end, not being the same as you would find if you use a real C/C++ compiler

Where did you get that idea? The Arduino compiler is just an AVR version of the popular GCC compiler. There is absolutely nothing wrong with it, and it certainly can handle floating point functions.

Problem is the people who developed the Arduino IDE decided to leave out the floating point support. It's simply a matter of the IDE not generating the proper GCC compile and link strings to send to the compiler.

The reason the FP code is not linked in is because it takes up about 2K of space, and we don't want people with a 32K microcontroller to write a 5K program and then use another 2.5K for floating point. No, sir! We have to keep as much flash memory unused as possible!

The IDE want from version 1.0 to 1.06 to what now? 1.6.5 and still the requests for floating point support (and printf\_P support) have gone unheard.

It takes literally less than 10 minutes to write a few extra lines of code to add an OPTION in the IDE to use or not use floating point.

Can you imagine how much torn out hair would finally be growing back by now if people could just click **[] Floating Point** instead of wondering what the darn question mark means and discovering that it's actually NOT their fault or a mistake in programming?

(sense my frustration you can, mmmmmm?) \<- Yoda voice

---

<div class="post-metadata">

**Author:** ![nickgammon](https://avatars.discourse-cdn.com/v4/letter/n/45deac/32.png) [@nickgammon](https://forum.arduino.cc/u/nickgammon)\
**Post date:** [August 28, 2015, 5:30am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/5 "2015-08-28T05:30:52Z")

</div>

Yes, but you can use dtostrf if you want to print floats. People who are already struggling with program size won't want the extra 2 KB included, if they don't even print floats ever.

The option idea might be one work-around, but then you get people complaining that the code you posted "doesn't work" because you have the option checked and they don't.

---

<div class="post-metadata">

**Author:** ![pYro\_65](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pyro_65/32/214665_2.png) [@pYro\_65](https://forum.arduino.cc/u/pYro_65)\
**Post date:** [August 28, 2015, 5:32am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/6 "2015-08-28T05:32:07Z")

</div>

If you have 1.6.5 and above, you can download my PrintEx library from the library manager.  
Or it can be manually installed in versions 1.5.x and up.

Among other things, it includes printf with floating point support.

```plaintext
#include <PrintEx.h>

PrintEx serial = Serial;

void setup(){
  Serial.begin(9600);
  serial.printf("/%31n\\\n| A floating point number: %f |\n\\%31n/", '=', 3.14f, '=' );
}

void loop() {}

```

Produces:

```plaintext
/===============================\
| A floating point number: 3.14 |
\===============================/

```

The readme has an overview of its usage.  
[https://github.com/Chris--A/PrintEx](https://github.com/Chris--A/PrintEx#printex-library-for-arduino-)

---

<div class="post-metadata">

**Author:** ![krupski](https://avatars.discourse-cdn.com/v4/letter/k/c4cdca/32.png) [@krupski](https://forum.arduino.cc/u/krupski)\
**Post date:** [August 31, 2015, 3:39am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/7 "2015-08-31T03:39:28Z")

</div>

> [@](#):
>
> Yes, but you can use dtostrf if you want to print floats. **People who are already struggling with program size won't want the extra 2 KB included, if they don't even print floats ever.**
> 
> The option idea might be one work-around, but then you get people complaining that the code you posted "doesn't work" because you have the option checked and they don't.

Honestly... when has someone ever struggled with program size? I know a lot of people THINK they are "out of memory" due to having strings in SRAM instead of PROGMEM, but who ever runs out of FLASH?

Not to mention the tricky syntax that dtostrf uses.

![preferences.jpg](https://europe1.discourse-cdn.com/arduino/original/4X/a/3/d/a3dffdfdfd699766f8db89efad1526c5ff839a61.jpeg)

Is a selectable preference REALLY so hard to use?

---

<div class="post-metadata">

**Author:** ![RayLivingston](https://avatars.discourse-cdn.com/v4/letter/r/b5ac83/32.png) [@RayLivingston](https://forum.arduino.cc/u/RayLivingston)\
**Post date:** [August 31, 2015, 3:42am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/8 "2015-08-31T03:42:57Z")

</div>

> Krupski:  
> Honestly... when has someone ever struggled with program size? I know a lot of people THINK they are "out of memory" due to having strings in SRAM instead of PROGMEM, but who ever runs out of FLASH?

I am very nearly out of FLASH on one of my products running on a ProMini, and there is very little left that can be optimized further. There is just a LOT of functionality in there. It's not at all rare, or even unusual.

Regards,  
Ray L.

---

<div class="post-metadata">

**Author:** ![krupski](https://avatars.discourse-cdn.com/v4/letter/k/c4cdca/32.png) [@krupski](https://forum.arduino.cc/u/krupski)\
**Post date:** [August 31, 2015, 3:44am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/9 "2015-08-31T03:44:28Z")

</div>

> pYro\_65:  
> If you have 1.6.5 and above, you can download my PrintEx library from the library manager.  
> Or it can be manually installed in versions 1.5.x and up.
> 
> Among other things, it includes printf with floating point support.
> 
> ```arduino
> #include <PrintEx.h>
> 
> ```

PrintEx serial = Serial;

void setup(){  
&nbsp;Serial.begin(9600);  
&nbsp;serial.printf("/%31n\\n| A floating point number: %f |\n\%31n/", '=', 3.14f, '=' );  
}

void loop() {}

> ```arduino
> 
> Produces:
> 
> ```
> 
> /===============================  
> | A floating point number: 3.14 |  
> ===============================/
> 
> ```arduino
> 
> The readme has an overview of its usage.
> [https://github.com/Chris--A/PrintEx](https://github.com/Chris--A/PrintEx#printex-library-for-arduino-)
> 
> ```

```arduino
    fprintf (stdout, "I like cherry PI! %.2f\n", M_PI);

```

...produces

```arduino
[b]I like cherry PI! 3.14[/b]

```

...no special library required. 🙂

---

<div class="post-metadata">

**Author:** ![krupski](https://avatars.discourse-cdn.com/v4/letter/k/c4cdca/32.png) [@krupski](https://forum.arduino.cc/u/krupski)\
**Post date:** [August 31, 2015, 3:47am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/10 "2015-08-31T03:47:24Z")

</div>

> RayLivingston:  
> I am very nearly out of FLASH on one of my products running on a ProMini, and there is very little left that can be optimized further. There is just a LOT of functionality in there. It's not at all rare, or even unusual.
> 
> Regards,  
> Ray L.

I'm not saying it NEVER happens (running out of flash). I'm just sure it's quite rare... and that's the point of having the FP library linkage as an _OPTION_... to turn it off if you need the last byte of space.

---

<div class="post-metadata">

**Author:** ![nickgammon](https://avatars.discourse-cdn.com/v4/letter/n/45deac/32.png) [@nickgammon](https://forum.arduino.cc/u/nickgammon)\
**Post date:** [August 31, 2015, 6:02am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/11 "2015-08-31T06:02:35Z")

</div>

> Krupski:  
> Is a selectable preference REALLY so hard to use?

No, if people know they exist. I have done a lot of support for software where people ask how do you do so-and-so and you say "check the box in the configuration dialog" and they reply "what? there's a configuration dialog"?

That's what you have to deal with.

---

<div class="post-metadata">

**Author:** ![pYro\_65](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pyro_65/32/214665_2.png) [@pYro\_65](https://forum.arduino.cc/u/pYro_65)\
**Post date:** [August 31, 2015, 6:12am UTC](https://forum.arduino.cc/t/printf-with-floats/332051/12 "2015-08-31T06:12:26Z")

</div>

> Krupski:
> 
> ```arduino
>     fprintf (stdout, "I like cherry PI! %.2f\n", M_PI);
> 
> ```
> 
> ...produces
> 
> ```arduino
> [b]I like cherry PI! 3.14[/b]
> 
> ```
> 
> ...no special library required. 🙂

No, but a special part of the Arduino program is required, then it needs recompiling....

Really???

---

<div class="post-metadata">

**Author:** ![HazardsMind](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/hazardsmind/32/215209_2.png) [@HazardsMind](https://forum.arduino.cc/u/HazardsMind)\
**Post date:** [September 2, 2015, 5:16pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/13 "2015-09-02T17:16:45Z")

</div>

There is something I don't understand, perhaps someone can shed some light on this.

Here is the function for dtostrf()

> char \*dtostrf (double val, signed char width, unsigned char prec, char \*sout) {  
> char fmt[20];  
> sprintf(fmt, "%%%d.%df", width, prec);  
> sprintf(sout, fmt, val);  
> return sout;  
> }

It uses sprintf twice and it also uses f in the format.

Why is this better to use than my function that doesn't use sprintf at all and yet still converts the float value to a string?

## dtostrf uses 2028 bytes mine uses 1894 bytes.

134 byte difference  
I can't test speed as I don't have a board to upload it to.

---

<div class="post-metadata">

**Author:** ![oqibidipo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/oqibidipo/32/221794_2.png) [@oqibidipo](https://forum.arduino.cc/u/oqibidipo)\
**Post date:** [September 2, 2015, 6:29pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/14 "2015-09-02T18:29:55Z")

</div>

That version is for ARM-based targets that have plenty of Flash for a full printf version.  
The original AVR version does not use printf.

---

<div class="post-metadata">

**Author:** ![HazardsMind](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/hazardsmind/32/215209_2.png) [@HazardsMind](https://forum.arduino.cc/u/HazardsMind)\
**Post date:** [September 2, 2015, 7:19pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/15 "2015-09-02T19:19:13Z")

</div>

Now allows negative floating values.

```cpp
/*
  Had to make my own pow() function as the standard pow() has a return type of double,
  and for some reason type casting from a double to an int produces 1 less that of the value.
  Ex. int(pow(10, 3)) returns 999 instead of 1000. (using IDE 1.6.0 on an UNO)
*/

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);

  char myB[10]; // buffer
  //ftos(myB, 4, 3, 1234.567); // 450 bytes IDE 1.6.0 using Uno R3
  dtostrf(1234.567, 4, 3, myB); // 2,028 bytes IDE 1.6.0 using Uno R3
  Serial.println(myB);
}

void loop() {
  // put your main code here, to run repeatedly:
}

char * ftos(char * buf, byte W, byte D, float data)
{
  byte shf = 0;
  if (data < 0)
  {
    data *= -1;
    shf = 1;
    buf[0] = '-';
  }
  long Wdata = data, tmp;
  float dec = data - long(data);

  // get the first whole number and convert it
  buf[0 + shf] = Wdata / Pow(10, W - 1) + '0';
  tmp = Wdata % Pow(10, W - 1);

  //now get the rest of the whole numbers
  for (byte i = 1; i < W; i++)
  {
    long factor = Pow(10, W - 1 - i);
    buf[i + shf] = (tmp / factor) + '0';
    tmp %= factor;
  }

  buf[W + shf] = '.'; // add the decimal point

  // now do the decimal numbers
  for (byte i = 0; i < D; i++)
  {
    dec *= 10;
    buf[W + i + 1 + shf] = (long(dec) % 10) + '0';
  }
  // don't forget the NULL terminator
  buf[W + D + 1 + shf] = NULL;
  return buf;
}

unsigned long Pow(long V, byte shift)
{
  unsigned long Val = 1;
  while (shift-- != 0)
    Val *= V;

  return Val;
}

```

---

<div class="post-metadata">

**Author:** ![HazardsMind](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/hazardsmind/32/215209_2.png) [@HazardsMind](https://forum.arduino.cc/u/HazardsMind)\
**Post date:** [September 2, 2015, 11:57pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/16 "2015-09-02T23:57:27Z")

</div>

Code:

```cpp
/*
  Had to make my own pow() function as the standard pow() has a return type of double,
  and for some reason type casting from a double to an int produces 1 less that of the value.
  Ex. int(pow(10, 3)) returns 999 instead of 1000. (using IDE 1.6.0 on an UNO)
*/

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);

  char myB[10]; // buffer
  char myB2[10];
  
  unsigned long current = micros();
  ftos(-1234.567, 4, 3, myB);
  Serial.println(micros() - current);
  
  delay(1);
  
  current = micros();
  dtostrf(-1234.567, 4, 3, myB2);
  Serial.println(micros() - current);
  
  Serial.println(myB);
  Serial.println(myB2);
}

void loop() {
  // put your main code here, to run repeatedly:
}

char * ftos(float data, byte W, byte D, char * buf)
{
  byte shf = 0;
  if (data < 0)
  {
    data *= -1;
    shf = 1;
    buf[0] = '-';
  }
  long Wdata = data, tmp;
  float dec = data - long(data);

  // get the first whole number and convert it
  buf[0 + shf] = Wdata / Pow(10, W - 1) + '0';
  tmp = Wdata % Pow(10, W - 1);

  //now get the rest of the whole numbers
  for (byte i = 1; i < W; i++)
  {
    long factor = Pow(10, W - 1 - i);
    buf[i + shf] = (tmp / factor) + '0';
    tmp %= factor;
  }

  buf[W + shf] = '.'; // add the decimal point

  // now do the decimal numbers
  for (byte i = 0; i < D; i++)
  {
    dec *= 10;
    buf[W + i + 1 + shf] = (long(dec) % 10) + '0';
  }
  // don't forget the NULL terminator
  buf[W + D + 1 + shf] = NULL;
  return buf;
}

unsigned long Pow(long V, byte shift)
{
  unsigned long Val = 1;
  while (shift-- != 0)
    Val *= V;

  return Val;
}

```

Speed results:  
Positive number: 1234.567  
ftos: 132 microseconds @ 2,388 bytes  
dtostrf: 108 microseconds @ 3,680 bytes  
diff: 1,292 bytes 22.2% slower

Negative Number: -1234.567  
ftos: 424 microseconds @ 3,644 bytes  
dtostrf: 108 microseconds @ 3680 bytes  
diff: 36 bytes 292.6% slower (damn)

Conclusion: mine lost on speed, but it won in lowest memory usage.

---

<div class="post-metadata">

**Author:** ![ctkjose](https://avatars.discourse-cdn.com/v4/letter/c/58956e/32.png) [@ctkjose](https://forum.arduino.cc/u/ctkjose)\
**Post date:** [September 3, 2019, 10:14pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/17 "2019-09-03T22:14:09Z")

</div>

I know this topic is old but just to help other on this topic:

I made a small and simple printf like function for interpolation.

> <https://gist.github.com/ctkjose/09aaed811802ab083f0771a007ac9fcd>

---

<div class="post-metadata">

**Author:** ![krupski](https://avatars.discourse-cdn.com/v4/letter/k/c4cdca/32.png) [@krupski](https://forum.arduino.cc/u/krupski)\
**Post date:** [September 5, 2019, 3:50pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/18 "2019-09-05T15:50:08Z")

</div>

> ctkjose:  
> I know this topic is old but just to help other on this topic:
> 
> I made a small and simple printf like function for interpolation.
> 
> [A simple printf like interpolation for Arduino · GitHub](https://gist.github.com/ctkjose/09aaed811802ab083f0771a007ac9fcd)

Check out my Arduino library for providing printf:

> **[GitHub - krupski/Stdinout: Standard input/output/error support for Arduino](https://github.com/krupski/Stdinout)**
>
> Standard input/output/error support for Arduino. Contribute to krupski/Stdinout development by creating an account on GitHub.

All you do is either make a new directory in "libraries" named "Stdinout" and copy the .cpp and .h files into it, or "install" the library using the IDE.

Now, say you want to use printf with the serial port. After opening the serial port as usual, simply add the line

```arduino
Stdio.open (Serial);

```

to your code. Of course, you first need to **#include "Stdinout"** in your sketch!

Note that this only provides stdin/out/err support - it does not give you floating point.

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [May 5, 2021, 9:27pm UTC](https://forum.arduino.cc/t/printf-with-floats/332051/19 "2021-05-05T21:27:21Z")

</div>


