Format double to at least one significant digit in Java/Android
Asked Answered
G

2

6

I have a DecimalFormat object which I'm using to format all of my double values to a set number of digits (let's say 2) when I'm displaying them. I would like it to normally format to 2 decimal places, but I always want at least one significant digit. For example, if my value is 0.2 then my formatter spits out 0.20 and that's great. However, if my value is 0.000034 my formatter will spit out 0.00 and I would prefer my formatter spit out 0.00003.

The number formatters in Objective-C do this very simply, I can just set a max number of digits I want to show at 2 and the minimum number of significant digits at 1 and it produces my desired output, but how can I do it in Java?

I appreciate any help anyone can offer me.

Kyle

Edit: I'm interested in rounding the values so 0.000037 displays as 0.00004.

Glendaglenden answered 12/12, 2010 at 23:36 Comment(0)
L
2

It's not efficient, so if you perform this operation often I'd try another solution, but if you only call it occasionally this method will work.

import java.text.DecimalFormat;
public class Rounder {
    public static void main(String[] args) {
        double value = 0.0000037d;
        // size to the maximum number of digits you'd like to show
        // used to avoid representing the number using scientific notation
        // when converting to string
        DecimalFormat maxDigitsFormatter = new DecimalFormat("#.###################");
        StringBuilder pattern = new StringBuilder().append("0.00");
        if(value < 0.01d){
            String s = maxDigitsFormatter.format(value);
            int i = s.indexOf(".") + 3;
            while(i < s.length()-1){
                pattern.append("0");
                i++;
            }
        }
        DecimalFormat df = new DecimalFormat(pattern.toString());
        System.out.println("value           = " + value);
        System.out.println("formatted value = " + maxDigitsFormatter.format(value));
        System.out.println("pattern         = " + pattern);
        System.out.println("rounded         = " + df.format(value));
    }
}
Lipp answered 15/12, 2010 at 18:26 Comment(1)
Thanks, cyber-monk, that looks like just about exactly what I need!Glendaglenden
I
0
import java.math.BigDecimal;
import java.math.MathContext;


public class Test {

    public static void main(String[] args) {
        String input = 0.000034+"";
        //String input = 0.20+"";
        int max = 2;
        int min =1;
        System.out.println(getRes(input,max,min));
    }

    private static String getRes(String input,int max,int min) {
        double x = Double.parseDouble(((new BigDecimal(input)).unscaledValue().intValue()+"").substring(0,min));
        int n = (new BigDecimal(input)).scale();
        String res = new BigDecimal(x/Math.pow(10,n)).round(MathContext.DECIMAL64).setScale(n).toString();
        if(n<max){
            for(int i=0;i<max;i++){
                res+="0";
            }
        }
        return res;
    }
}
Incomprehension answered 13/12, 2010 at 14:35 Comment(2)
Hey Zawhtut! First off, thanks for the reply. I do have a couple of additional questions, though. First, I'm interested in rounding rather than truncating, so I'd want 0.000037 to be represented as 0.00004 rather than 0.00003. Second, if my original number is 0.0000372, it appears to me that the algorithm you provided will yield 3e-7, due to the fact that the last significant figure of my input number is as the e-7 place. Am I off base on that? Thanks again for any additional clarification you can provide!Glendaglenden
Hey Kyle. Seems like you already has an answer. A good question by the way.Incomprehension

© 2022 - 2024 — McMap. All rights reserved.