#include <stdio.h>
/*
Because lcd and serial don't support printf, and its very costly, and all we need
is simple formating with a certain number of digits and precision, this ftoa is enough.
If you need more, see:
https://g...content-available-to-author-only...b.com/charlesnicholson/nanoprintf
*/
//avoid needed stdlib.h by defining abs as a macro
#define absq(amt) ((amt)<0?0-(amt):(amt))
//avoid needing math.h by defining powers of 10 as an array
long pow10[10] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
int puts_int( //send positive integers to STDOUT via putchar(char)
unsigned int num //positive integer to display
,char digits //count of digits, negative and '0' pad for trailing zeros
,char pad //character to pad with, or null
) {
unsigned int i;
char c;
unsigned char d;
d = absq(digits);
while (0 < d) {
i = num/pow10[--d]; //pre-increment
if (d && !i) { //no digits found yet. d && for leading zero
if (pad
) putchar(pad
); else digits
--; //track digits (not) used }
else { //found something
c = i%10; //only want the lowest digit
//Optional: Don't continue after fraction done
if ('0'==pad && 0<digits && 0==c) return digits-d;
putchar(c
+'0'); //convert to ASCII and send }
}
return absq(digits)-d;
}
int puts_float( //send floating point numbers to STDOUT
float f //number to display
, char digits //digits, negative to pad with spaces
, char precision //precision, negative to keep trailing zeros
) {
unsigned int a;
char i=0;
if(digits>=10) {return 0;};
// check for negative float
if(f<0.0) { //is it negative?
f*=-1; //make it positive
if (0>digits) digits++; //optional, steal digit for sign, keep length
}
a=(int)f; // extract whole number
i+=puts_int(a,digits,digits>0?0:' ');
if (precision) {
f-=(float)a; //remove whole part
f*=pow10[absq(precision)]; // promote to precision
f+=0.5; // round
a=(int)f; // extract whole number
i+=puts_int(a,precision,'0');
}
return i; //count of characters
}
int main(void) {
float f;
//puts_int(12345,6,' ');puts("");
puts_float
(1.0000, -9, 4);putchar(' '); puts_float
(12345678.1234, 9, 4);putchar(' '); //8 digits no precision left. 9 digits fails puts_float
(100000000, 9, 4);putchar('\r'); //only 8 usable digits, but 9 digit numbers are ok. for (f
=0.0001;f
<0.00091;f
+=0.0001) { puts_float
(f
, 5, -4); putchar(' '); }; puts(""); for (f
=0.001;f
<0.0091;f
+=0.001) { puts_float
(f
, 5, -4); putchar(' '); }; puts(""); for (f
=0.01;f
<0.091;f
+=0.01) { puts_float
(f
, 5, -4); putchar(' '); }; puts(""); for (f
=0.1;f
<0.91;f
+=0.1) { puts_float
(f
, 5, -4); putchar(' '); }; puts(""); //also puts_int the return value of puts_float, which is the character used count.
puts_int
(puts_float
(123406.789, -8, 3),4,' ');putchar(',');putchar(' '); puts_int
(puts_float
(123450.789, 8, 0),4,' ');putchar('\r'); puts_int
(puts_float
(-4.4, -8, -4),4,' ');putchar('\r'); return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CgovKgpCZWNhdXNlIGxjZCBhbmQgc2VyaWFsIGRvbid0IHN1cHBvcnQgcHJpbnRmLCBhbmQgaXRzIHZlcnkgY29zdGx5LCBhbmQgYWxsIHdlIG5lZWQKaXMgc2ltcGxlIGZvcm1hdGluZyB3aXRoIGEgY2VydGFpbiBudW1iZXIgb2YgZGlnaXRzIGFuZCBwcmVjaXNpb24sIHRoaXMgZnRvYSBpcyBlbm91Z2guCklmIHlvdSBuZWVkIG1vcmUsIHNlZToKaHR0cHM6Ly9nLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5iLmNvbS9jaGFybGVzbmljaG9sc29uL25hbm9wcmludGYKKi8KCi8vYXZvaWQgbmVlZGVkIHN0ZGxpYi5oIGJ5IGRlZmluaW5nIGFicyBhcyBhIG1hY3JvCiNkZWZpbmUgYWJzcShhbXQpICgoYW10KTwwPzAtKGFtdCk6KGFtdCkpCi8vYXZvaWQgbmVlZGluZyBtYXRoLmggYnkgZGVmaW5pbmcgcG93ZXJzIG9mIDEwIGFzIGFuIGFycmF5CmxvbmcgcG93MTBbMTBdID0gezEsMTAsMTAwLDEwMDAsMTAwMDAsMTAwMDAwLDEwMDAwMDAsMTAwMDAwMDAsMTAwMDAwMDAwLDEwMDAwMDAwMDB9OwoKaW50IHB1dHNfaW50KCAvL3NlbmQgcG9zaXRpdmUgaW50ZWdlcnMgdG8gU1RET1VUIHZpYSBwdXRjaGFyKGNoYXIpCiAgIHVuc2lnbmVkIGludCBudW0JLy9wb3NpdGl2ZSBpbnRlZ2VyIHRvIGRpc3BsYXkKICAsY2hhciBkaWdpdHMJLy9jb3VudCBvZiBkaWdpdHMsIG5lZ2F0aXZlIGFuZCAnMCcgcGFkIGZvciB0cmFpbGluZyB6ZXJvcwogICxjaGFyIHBhZAkJLy9jaGFyYWN0ZXIgdG8gcGFkIHdpdGgsIG9yIG51bGwgCiAgKSB7CnVuc2lnbmVkIGludCBpOwpjaGFyIGM7CnVuc2lnbmVkIGNoYXIgZDsKICBkID0gYWJzcShkaWdpdHMpOwogIHdoaWxlICgwIDwgZCkgewogICAgaSA9IG51bS9wb3cxMFstLWRdOyAvL3ByZS1pbmNyZW1lbnQKICAgIGlmIChkICYmICFpKSB7IC8vbm8gZGlnaXRzIGZvdW5kIHlldC4gZCAmJiBmb3IgbGVhZGluZyB6ZXJvCiAgICAgIGlmIChwYWQpIHB1dGNoYXIocGFkKTsgZWxzZSBkaWdpdHMtLTsgLy90cmFjayBkaWdpdHMgKG5vdCkgdXNlZAogICAgICB9CiAgICBlbHNlIHsgLy9mb3VuZCBzb21ldGhpbmcKICAgICAgYyA9IGklMTA7IC8vb25seSB3YW50IHRoZSBsb3dlc3QgZGlnaXQKICAgICAgLy9PcHRpb25hbDogRG9uJ3QgY29udGludWUgYWZ0ZXIgZnJhY3Rpb24gZG9uZQogICAgICBpZiAoJzAnPT1wYWQgJiYgMDxkaWdpdHMgJiYgMD09YykgcmV0dXJuIGRpZ2l0cy1kOyAKICAgICAgcHV0Y2hhcihjKycwJyk7IC8vY29udmVydCB0byBBU0NJSSBhbmQgc2VuZAogICAgICB9CiAgICB9CiAgcmV0dXJuIGFic3EoZGlnaXRzKS1kOwogIH0KCmludCBwdXRzX2Zsb2F0KCAvL3NlbmQgZmxvYXRpbmcgcG9pbnQgbnVtYmVycyB0byBTVERPVVQKICAgIGZsb2F0IGYgIAkvL251bWJlciB0byBkaXNwbGF5CiAgLCBjaGFyIGRpZ2l0cwkvL2RpZ2l0cywgbmVnYXRpdmUgdG8gcGFkIHdpdGggc3BhY2VzCiAgLCBjaGFyIHByZWNpc2lvbgkvL3ByZWNpc2lvbiwgbmVnYXRpdmUgdG8ga2VlcCB0cmFpbGluZyB6ZXJvcwogICkgewp1bnNpZ25lZCBpbnQgYTsKY2hhciBpPTA7CgogIGlmKGRpZ2l0cz49MTApIHtyZXR1cm4gMDt9OwovLyBjaGVjayBmb3IgbmVnYXRpdmUgZmxvYXQKICBpZihmPDAuMCkgeyAvL2lzIGl0IG5lZ2F0aXZlPwogICAgcHV0Y2hhcignLScpO2krKzsgLy9pbmRpY2F0ZQogICAgZio9LTE7IC8vbWFrZSBpdCBwb3NpdGl2ZQogICAgaWYgKDA+ZGlnaXRzKSBkaWdpdHMrKzsgLy9vcHRpb25hbCwgc3RlYWwgZGlnaXQgZm9yIHNpZ24sIGtlZXAgbGVuZ3RoCiAgICB9CgogIGE9KGludClmOwkvLyBleHRyYWN0IHdob2xlIG51bWJlcgogIGkrPXB1dHNfaW50KGEsZGlnaXRzLGRpZ2l0cz4wPzA6JyAnKTsKICBpZiAocHJlY2lzaW9uKSB7CiAgICBwdXRjaGFyKCcuJyk7aSsrOwogICAgZi09KGZsb2F0KWE7IC8vcmVtb3ZlIHdob2xlIHBhcnQKICAgIGYqPXBvdzEwW2Fic3EocHJlY2lzaW9uKV07IC8vIHByb21vdGUgdG8gcHJlY2lzaW9uCiAgICBmKz0wLjU7IC8vIHJvdW5kCiAgICBhPShpbnQpZjsgLy8gZXh0cmFjdCB3aG9sZSBudW1iZXIKICAgIGkrPXB1dHNfaW50KGEscHJlY2lzaW9uLCcwJyk7CiAgICB9CiAgcmV0dXJuIGk7IC8vY291bnQgb2YgY2hhcmFjdGVycwogIH0KCgppbnQgbWFpbih2b2lkKSB7CmZsb2F0IGY7CiAgLy9wdXRzX2ludCgxMjM0NSw2LCcgJyk7cHV0cygiIik7CiAgcHV0c19mbG9hdCgxLjAwMDAsIC05LCA0KTtwdXRjaGFyKCcgJyk7CiAgcHV0c19mbG9hdCgxMjM0NTY3OC4xMjM0LCA5LCA0KTtwdXRjaGFyKCcgJyk7IC8vOCBkaWdpdHMgbm8gcHJlY2lzaW9uIGxlZnQuIDkgZGlnaXRzIGZhaWxzCiAgcHV0c19mbG9hdCgxMDAwMDAwMDAsIDksIDQpO3B1dGNoYXIoJ1xyJyk7IC8vb25seSA4IHVzYWJsZSBkaWdpdHMsIGJ1dCA5IGRpZ2l0IG51bWJlcnMgYXJlIG9rLgogIGZvciAoZj0wLjAwMDE7ZjwwLjAwMDkxO2YrPTAuMDAwMSkgeyBwdXRzX2Zsb2F0KGYsIDUsIC00KTsgcHV0Y2hhcignICcpOyB9OyBwdXRzKCIiKTsKICBmb3IgKGY9MC4wMDE7ZjwwLjAwOTE7Zis9MC4wMDEpIHsgcHV0c19mbG9hdChmLCA1LCAtNCk7IHB1dGNoYXIoJyAnKTsgfTsgcHV0cygiIik7CiAgZm9yIChmPTAuMDE7ZjwwLjA5MTtmKz0wLjAxKSB7IHB1dHNfZmxvYXQoZiwgNSwgLTQpOyBwdXRjaGFyKCcgJyk7IH07IHB1dHMoIiIpOwogIGZvciAoZj0wLjE7ZjwwLjkxO2YrPTAuMSkgeyBwdXRzX2Zsb2F0KGYsIDUsIC00KTsgcHV0Y2hhcignICcpOyB9OyBwdXRzKCIiKTsKICAvL2Fsc28gcHV0c19pbnQgdGhlIHJldHVybiB2YWx1ZSBvZiBwdXRzX2Zsb2F0LCB3aGljaCBpcyB0aGUgY2hhcmFjdGVyIHVzZWQgY291bnQuCiAgcHV0c19pbnQocHV0c19mbG9hdCgxMjM0MDYuNzg5LCAtOCwgMyksNCwnICcpO3B1dGNoYXIoJywnKTtwdXRjaGFyKCcgJyk7CiAgcHV0c19pbnQocHV0c19mbG9hdCgxMjM0NTYsIDgsIC0zKSw0LCcgJyk7cHV0Y2hhcignLCcpO3B1dGNoYXIoJyAnKTsKICBwdXRzX2ludChwdXRzX2Zsb2F0KDEyMzQ1MC43ODksIDgsIDApLDQsJyAnKTtwdXRjaGFyKCdccicpOwogIHB1dHNfaW50KHB1dHNfZmxvYXQoLTQuNCwgOCwgNCksNCwnICcpO3B1dGNoYXIoJywnKTtwdXRjaGFyKCcgJyk7CiAgcHV0c19pbnQocHV0c19mbG9hdCgtNC40LCAtOCwgLTQpLDQsJyAnKTtwdXRjaGFyKCdccicpOwogIHJldHVybiAwOwp9Cg==