What is the Java equivalent of C's printf %g format specifier?

John Douthat picture John Douthat · May 16, 2009 · Viewed 7.2k times · Source

I tried using Formatter.format, but that seems to leave the mantissa on numbers with 0 mantissa, whereas the C version does not. Is there an equivalent of C's %g format specifier in Java, and if not, is there a way to fake it? My intention is to preserve the mantissa exactly like C's for compatibility reasons.

foo.c

#include <stdio.h>

int main (int argc, char const *argv[])
{
    printf("%g\n", 1.0);
    return 0;
}

Main.java

class Main {
        public static void main(String[] args) {
                System.out.printf("%g\n", 1.0);
        }
}

Console:

$ javac Main.java && java Main
1.00000
$ gcc foo.c && ./a.out
1

Similarly, with 1.2 as input, the mantissa is longer in Java's version

$ javac Main.java && java Main
1.20000
$ gcc foo.c && ./a.out
1.2

Answer

John Douthat picture John Douthat · May 17, 2009

edit: This code causes the fractional part to go missing if the exponent is 17 digits, because of my misunderstanding of how String.format formatted those numbers. So don't please don't use this code :P

Thanks for the input, guys. I couldn't find a way to configure DecimalFormat or NumberFormat to exactly clone the functionality, but it seems this method works (followed by an example):

String.format("%.17g", x).replaceFirst("\\.?0+(e|$)", "$1");

main.c

#include <stdio.h>

int main (int argc, char const *argv[])
{
    printf("%.*g\n", 17, -0.0);
    printf("%.*g\n", 17, 0.0);
    printf("%.*g\n", 17, 1.0);
    printf("%.*g\n", 17, 1.2);
    printf("%.*g\n", 17, 0.0000000123456789);
    printf("%.*g\n", 17, 1234567890000000.0);
    printf("%.*g\n", 17, 0.0000000123456789012345678);
    printf("%.*g\n", 17, 1234567890123456780000000.0);
    return 0;
}

Main.java

class Main {
        public static String formatDouble(double x) {
                return String.format("%.17g", x).replaceFirst("\\.?0+(e|$)", "$1");
        }

        public static void main(String[] args) {
                System.out.println(formatDouble(-0.0));
                System.out.println(formatDouble(0.0));
                System.out.println(formatDouble(1.0));
                System.out.println(formatDouble(1.2));
                System.out.println(formatDouble(0.0000000123456789));
                System.out.println(formatDouble(1234567890000000.0));
                System.out.println(formatDouble(0.0000000123456789012345678));
                System.out.println(formatDouble(1234567890123456780000000.0));
        }
}

and their outputs:

$ gcc foo.c && ./a.out
-0
0
1
1.2
1.23456789e-08
1234567890000000
1.2345678901234567e-08
1.2345678901234568e+24
$ javac Main.java && java Main
-0
0
1
1.2
1.23456789e-08
1234567890000000
1.2345678901234567e-08
1.2345678901234568e+24