Printf with floats
James Stanley

I am just wondering if there is a way to make printf() handle floats sanely.
For example I have the numbers 6 and 73.03, I would like printf() to print '6' and '73.03'. Instead of '6.000000' and '73.030000' or '6' and '73', or '6.00' and '73.03'.

Is there a printf() modifier to make this happen or will I have to calculate this myself?

Richard Phipps

Yes, there is.. do a search on google. I think you want to look for %f, %0, etc..

ReyBrujo

%02f gives 2 decimal numbers padded with 0. %2f gives up to 2 decimal numbers without padding.

James Stanley

Richard Phipps, I have already done that to no avail.
ReyBrujo, %2f still printed out 6 decimal places. %02f did the same.

ReyBrujo

Wait, sorry, %.2f instead of %2f

James Stanley

That's closer, but it always prints 2 decimal places regardless of the actual value.

Northburns

I was going to give you some tips on building a function to do that, but I wasn't totally sure how to do it, so I tried to first make that function and then help. But now that I have a semi-working thingie in my text editor, I'd feel bad not to give it out: (with a smell test program, which has memory leaks :))

1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4 
5 
6 
7char * floatToSane(float x);
8 
9int main(void) {
10 printf("%f\n",(float)32);
11 printf("%s\n",floatToSane((float)32));
12 printf("%f\n",(float)0.32);
13 printf("%s\n",floatToSane((float)0.32));
14 
15 return 0;
16}
17 
18#define BUFFER_SIZE 32
19char * floatToSane(float x) {
20 char * end; //This points to the last character of the string
21 char * i = (char*)malloc(BUFFER_SIZE*sizeof(char)); //The returned string
22 sprintf(i,"%f",x); //Acquire the "insane" float-printf
23 end = i + (strlen(i)-1)*sizeof(char); //Calculate the address of the last character
24 while(*end == '0') { //Destroy all trailing zeroes
25 *end = '\0';
26 end--;
27 }
28 if(*end == '.') { //If all zeroes after decimal point -> destroy decimal point
29 *end = '\0';
30 }
31
32 return i;
33}

This is one way of doing it. floatToSane()-functions 2nd line (char * i = ...) is a bit dumb, there has to be a better way.. But I'm tired and really wanna get some sleep.
I hope that helps! Make my function better.

ReyBrujo

Better to use a static buffer instead of malloc. Or even better, receive the buffer as argument.

James Stanley

Northburns, thanks for that function, I'll use that.
What license is it under? Public domain?

Edgar Reynaldo

http://www.cppreference.com/stdio/printf.html
It tells you how to pad the field, specify how many characters are displayed and the amount of precision and also specify whether it is right justified (default) or left justified.

James Stanley

I've already seen that page. I tried some of the stuff and it just didn't work.
I'm guessing this is because it's a C++ site.

EDIT:
And I'm using C.

Edgar Reynaldo

If you look at The index of the cppreference.com site you'll see it is for C and C++.

It works just fine and it is C code. Try again, here's an example.

using_printf_with_floats.c

1#include <stdio.h>
2 
3 
4int main() {
5
6 const double pie = 3.14159265;
7
8 printf("%-5.3f\n" , pie);
9 printf("%7.2f\n" , pie);
10 printf("%08.4f\n" , pie);
11
12
13
14 return 0;
15}

The output :

c:\ctwoplus\progcode\test>gcc -Wall -o pftest.exe using_printf_with_floats.c

c:\ctwoplus\progcode\test>pftest
3.142
   3.14
003.1416

c:\ctwoplus\progcode\test>

Northburns
James Stanley said:

Northburns, thanks for that function, I'll use that.
What license is it under? Public domain?

License?.. Consider it a gift. So I guess Public domain is pretty accurate. Consider ReyBrujo's suggestions:

ReyBrujo said:

Better to use a static buffer instead of malloc. Or even better, receive the buffer as argument.

Evert

I'm stunned.

Quote:

For example I have the numbers 6 and 73.03, I would like printf() to print '6' and '73.03'. Instead of '6.000000' and '73.030000' or '6' and '73', or '6.00' and '73.03'.

Is there a printf() modifier to make this happen or will I have to calculate this myself?

There is: %g.

Northburns

%g prints the shorter of %e and %f. But if the numbers are not very small or very big or you don't mind the scientific format, then %g is much better option.

Fladimir da Gorf

Northburns: snprintf!! No one should ever consider coding in C if he doesn't use the nprint functions instead. I guess you don't want your program to turn into a Microsoft product?

Also, better to limit the number of decimal places before you acquire the "insane" text value. That's because floats are never perfectly accurate, so you may want some rounding to happen first.

ReyBrujo

%g rounds. 7.01 becomes 7 under it.

James Stanley

Edgar, when I get home I'll take a closer look at the options, but I'm fairly sure I tried everything that sounded relevant.
Northburns, thanks for it being public domain!
Fladimir, I converted it to snprintf before I even compiled it. ;)
EDIT:

Quote:

That's because floats are never perfectly accurate

I found that, and I rounded it to a maximum of 4 places.

Evert
Quote:

%g prints the shorter of %e and %f.

It will also drop the fractional part if it's all 0 to machine precission (actually, I'm not sure about the tolerance, so take that with a grain of salt).
I don't know if that's a GNU thing or not, but I know it does this (because I use it a lot).

Quote:

%g rounds. 7.01 becomes 7 under it.

Your C compiler is broken then.

Anyway:

#include <stdio.h>

int main(void)
{
   double f1 = 7.;
   double f2 = 7.01;

   printf("%g %g\n", f1, f2);
   return 0;
}

produces

7 7.01

James Stanley

%g does exactly what I want.
I didn't expect it to because that cppreference.com site said it does the shorter of %f and %e. Neither of those, AFAICT, does what %g does.
%f prints 6 places, %e prints in standard form.

Anyway, problem solved!

Thread #595514. Printed from Allegro.cc