Question

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
Was it helpful?

Solution

Have you tried the java.text.DecimalFormat class?

System.out.println(new DecimalFormat().format(1.0));

outputs:

1

whereas:

System.out.println(new DecimalFormat().format(1.2));

outputs:

1.2

OTHER TIPS

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

You could use a NumberFormat. By setting the minimum fraction digits to 0, but leaving the maximum bigger, it should do what you want.

It's not as easy as printf, but it should work.

well, you can specify how many digits you want: "%.2g" will display 1.2 as 1.20

Note that using

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

fails for 1.2345e-20 (strips the zero from the end, producing 1.2345e-2). Here is what I ended up using in my code:

String.format(Locale.US, "%.6g", x).replaceFirst("\\.0+(e|$)", "$1").replaceFirst("(\\.[0-9]*[1-9])(0+)(e|$)", "$1$3")

Basically I modified the expression to ensure only zeros at the end of the fractional part are removed and split this into two cases. But thanks for pointing me in the right direction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top