Conditional formatted output

120 Views Asked by At

I only have access to a function like this (mean I cannot change the input or signature for this function):

public void log( String fmt , final Object... args )
{
    fmt = fmt.replace( "%f" , "%1.3e" );
    System.out.print( String.format( Locale.US , fmt , args );
}

I'd like to change the fmt to contain either %5.2f or %1.3e (only examples) dependent on the actual decimal value it represents (to kind of achieve the same number of digits for every decimal value).

Lets say 6 digits + 1 dot:

1234.56789 becomes 1234.56
123.456789 becomes 123.456
12.3456789 becomes 12.3456
...
0.00123456789  becomes 1.234e-3 
0.000123456789 becomes 1.234e-4
...

How would someone do that?

1

There are 1 best solutions below

0
ttzn On

By "same number of digits", I assume you mean "same number of characters", which is a common requirement for logging functions.

For 6 digits + 1 dots, the following code will output 7 characters for each number :

import java.util.Locale;

public class TestLog {
    public static void main(String[] args) {
        log("%f", 1234.56789);
        log("%f", 123.456789);
        log("%f", 1.3456789);
        log("%f", 0.0012345678);
        log("%f", 0.0001);

    }

    public static void log(String fmt, final Object... args) {
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof Number) {
                double d = (Double) args[i];
                if (d < 0.01) 
                    // Too small for precision 2, switch to scientific notation
                    fmt = fmt.replace("%f", "%07.1e");
                else
                    fmt = fmt.replace("%f", "%07.2f");
            }
        }

        System.out.println(String.format(Locale.US, fmt, args));
    }
}

The ouput being :

1234.57
0123.46
0001.35
1.2e-03
1.0e-04

In any case, the 07 part in the placeholders is the most important, because it guarantees the minimal width of the ouput. The leading 0 flag ensures that the output is padded with zeroes, but you can take it out if you want spaces instead.