48

Is it possible to format a float in C to only show up to 2 decimal places if different from 0s using printf?

Ex:

12 => 12

12.1 => 12.1

12.12 => 12.12

I tried using:

float f = 12;
printf("%.2f", f)

but I get

12 => 12.00

12.1 => 12.10

12.12 => 12.12

epignosisx
  • 6,152
  • 2
  • 30
  • 31

3 Answers3

64

You can use the %g format specifier:

#include <stdio.h>

int main() {
  float f1 = 12;
  float f2 = 12.1;
  float f3 = 12.12;
  float f4 = 12.1234;
  printf("%g\n", f1);
  printf("%g\n", f2);
  printf("%g\n", f3);
  printf("%g\n", f4);
  return 0;
}

Result:

12
12.1
12.12
12.1234

Note that, unlike the f format specifier, if you specify a number before the g it refers to the length of the entire number (not the number of decimal places as with f).

mechanical_meat
  • 163,903
  • 24
  • 228
  • 223
  • 5
    you still want to have the `%.2g` so that it limits to 2 decimal places. – twain249 Mar 09 '12 at 04:00
  • 3
    By the way, for the `f` format specifier the number represents decimal digits, but for `g` it is the total length of the number. – mechanical_meat Mar 09 '12 at 04:11
  • oops my mistake. How would that work if you don't know how many digits are before the decimal point? I know you could find it and use a variable size but that seems like a lot of work for that. – twain249 Mar 09 '12 at 04:14
  • That's a good point. The question Mike Kwan linked to has a brittle solution for that. Since the OP hasn't stated that as a specification I probably shouldn't have put a number in there. We'll see what the OP says :-) – mechanical_meat Mar 09 '12 at 04:17
  • 1
    wow that seems like a complicated why of doing it. I was thinking something like `sprintf(temp, "%f", f); temp2 = strchr(temp, '.'); i = temp2-temp; printf(%.*g\n", (i+2), f);` but I don't know if that will actually work. I think I'll go try it. – twain249 Mar 09 '12 at 04:22
  • 1
    Worked for me. obviously you have to define all the variables correctly. – twain249 Mar 09 '12 at 04:30
  • 12
    What is unfortunately not good about `%g`, is that it may truncate number and you will lose precision, for example `printf("%g", 1363262708.988428)` will give you `1.36326e+09`, however with `%f` it will print correctly (exactly `1363262708.988428`). – ivanzoid Mar 14 '13 at 12:23
  • 3
    @ivanzoid: the problem can be solved by using `"%.14g"` instead of just `"%g"` (I don't think the number 14 is too significant; that's what I found in Lua's source code). – Niccolo M. Apr 29 '14 at 13:14
  • The problem with %g is that it treats precision as the number of significant digits, not the number of digits after the decimal point: `printf("%.2g",0.01234)` prints `0.012`. It seems that if you want the correct (expected) behavior, you need to roll your own function. – riv Jul 17 '15 at 16:43
7

From our discussion in the above answer here is my program that works for any number of digits before the decimal.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    float f1 = 12.13;
    float f2 = 12.245;
    float f3 = 1242.145;
    float f4 = 1214.1;

    int i = 0;
    char *s1 = (char *)(malloc(sizeof(char) * 20));
    char *s2 = (char *)(malloc(sizeof(char) * 20));

    sprintf(s1, "%f", f1);
    s2 = strchr(s1, '.');
    i = s2 - s1;
    printf("%.*g\n", (i+2), f1);

    sprintf(s1, "%f", f2);
    s2 = strchr(s1, '.');
    i = s2 - s1;
    printf("%.*g\n", (i+2), f2);

    sprintf(s1, "%f", f3);
    s2 = strchr(s1, '.');
    i = s2 - s1;
    printf("%.*g\n", (i+2), f3);

    sprintf(s1, "%f", f4);
    s2 = strchr(s1, '.');
    i = s2 - s1;
    printf("%.*g\n", (i+2), f4);

    free(s1);
    free(s2);

    return 0;
}

And here's the output

12.13
12.24
1242.15
1214.1
twain249
  • 5,666
  • 1
  • 21
  • 26
6

For what it's worth, here's a simple ObjC implementation:

// Usage for Output   1 — 1.23
[NSString stringWithFormat:@"%@ — %@", [self stringWithFloat:1], 
                                       [self stringWithFloat:1.234];

// Checks if it's an int and if not displays 2 decimals.
+ (NSString*)stringWithFloat:(CGFloat)_float
{
    NSString *format = (NSInteger)_float == _float ? @"%.0f" : @"%.2f";
    return [NSString stringWithFormat:format, _float];
}

%g wasn't doing it for me — this one yes :-) Hope it's useful to some of you.

StuFF mc
  • 4,137
  • 2
  • 33
  • 32