[java] Java에서 소수점 이하 자릿수를 반올림하는 방법

내가 원하는 것은 double-up 방법을 사용하여 반올림하는 문자열로 double을 변환하는 방법입니다. 즉 반올림 할 소수점이 5 인 경우 항상 다음 숫자로 올림합니다. 이것은 대부분의 사람들이 대부분의 상황에서 기대하는 반올림의 표준 방법입니다.

또한 유효 숫자 만 표시하고 싶습니다. 즉, 0이 없어야합니다.

이 작업을 수행하는 한 가지 방법은 해당 String.format방법 을 사용하는 것입니다.

String.format("%.5g%n", 0.912385);

보고:

0.91239

중요하지만 중요하지 않은 경우에도 항상 소수점 이하 5 자리의 숫자를 표시합니다.

String.format("%.5g%n", 0.912300);

보고:

0.91230

다른 방법은 다음을 사용하는 것입니다 DecimalFormatter.

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

보고:

0.91238

그러나 당신이 볼 수 있듯이 반 반올림을 사용합니다. 즉, 이전 자릿수가 짝수이면 반올림됩니다. 내가 원하는 것은 이것입니다 :

0.912385 -> 0.91239
0.912300 -> 0.9123

Java에서 이것을 달성하는 가장 좋은 방법은 무엇입니까?



답변

을 사용하고 setRoundingMode, RoundingMode반올림 문제를 처리 하도록 명시 적으로 설정 한 다음 필요한 출력에 형식 패턴을 사용하십시오.

예:

DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
    Double d = n.doubleValue();
    System.out.println(df.format(d));
}

출력을 제공합니다.

12
123.1235
0.23
0.1
2341234.2125

편집 : 원래 답변은 이중 값의 정확성을 다루지 않습니다. 반올림 여부에 상관없이 괜찮습니다. 그러나 정확한 반올림을 원하면 예상되는 값의 정확도를 고려해야합니다. 부동 소수점 값은 내부적으로 이진 표현을 갖습니다. 즉, 2.7735와 같은 값은 실제로 정확한 값을 갖지 않습니다. 약간 크거나 작을 수 있습니다. 내부 값이 약간 작은 경우 2.7740으로 올림되지 않습니다. 이러한 상황을 해결하려면 작업중인 값의 정확성을 알고 반올림하기 전에 해당 값을 더하거나 빼야합니다. 예를 들어, 값이 최대 6 자리까지 정확하다는 것을 알고 반값을 반올림하려면 해당 정확도를 값에 추가하십시오.

Double d = n.doubleValue() + 1e-6;

반올림하려면 정확도를 뺍니다.


답변

가정 valueA는 double, 당신은 할 수 있습니다 :

(double)Math.round(value * 100000d) / 100000d

5 자리 정밀도입니다. 0의 수는 소수의 수를 나타냅니다.


답변

new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

당신을 얻을 것입니다 BigDecimal. 그것에서 문자열을 얻으려면, 그냥 전화 BigDecimaltoString방법, 또는 toPlainString일반 형식 문자열에 대한 자바에 대한 방법을 5+.

샘플 프로그램 :

package trials;
import java.math.BigDecimal;

public class Trials {

    public static void main(String[] args) {
        int yourScale = 10;
        System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
    }


답변

당신은 또한 사용할 수 있습니다

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

후행 0이 있는지 확인하십시오.


답변

다른 사람들이 지적했듯이 정답은 DecimalFormat또는 을 사용하는 것 BigDecimal입니다. 부동 소수점 에는 소수점 이하 자릿수가 없으므로 처음에는 특정 숫자로 반올림 / 잘라낼 수 없습니다. 십진 기수로 작업해야합니다. 이것이 두 클래스가하는 일입니다.

이 스레드의 모든 답변과 실제로 곱셈과 잘림, 나눗셈을 권장하는 StackOverflow (및 다른 곳)의 모든 답변에 대한 예제로 다음 코드를 게시하고 있습니다. 다음 코드가 92 % 이상의 경우에 잘못된 출력을 생성하는 이유를 설명하는 것은이 기술의 옹호자에 의한 것입니다.

public class RoundingCounterExample
{

    static float roundOff(float x, int position)
    {
        float a = x;
        double temp = Math.pow(10.0, position);
        a *= temp;
        a = Math.round(a);
        return (a / (float)temp);
    }

    public static void main(String[] args)
    {
        float a = roundOff(0.0009434f,3);
        System.out.println("a="+a+" (a % .001)="+(a % 0.001));
        int count = 0, errors = 0;
        for (double x = 0.0; x < 1; x += 0.0001)
        {
            count++;
            double d = x;
            int scale = 2;
            double factor = Math.pow(10, scale);
            d = Math.round(d * factor) / factor;
            if ((d % 0.01) != 0.0)
            {
                System.out.println(d + " " + (d % 0.01));
                errors++;
            }
        }
        System.out.println(count + " trials " + errors + " errors");
    }
}

이 프로그램의 출력 :

10001 trials 9251 errors

편집 : 내가 사용 테스트 루프의 계수 부분을 redid 아래 몇 가지 의견을 해결하기 위해, BigDecimal그리고 new MathContext(16)다음과 같이 계수 작업을 위해 :

public static void main(String[] args)
{
    int count = 0, errors = 0;
    int scale = 2;
    double factor = Math.pow(10, scale);
    MathContext mc = new MathContext(16, RoundingMode.DOWN);
    for (double x = 0.0; x < 1; x += 0.0001)
    {
        count++;
        double d = x;
        d = Math.round(d * factor) / factor;
        BigDecimal bd = new BigDecimal(d, mc);
        bd = bd.remainder(new BigDecimal("0.01"), mc);
        if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
        {
            System.out.println(d + " " + bd);
            errors++;
        }
    }
    System.out.println(count + " trials " + errors + " errors");
}

결과:

10001 trials 4401 errors


답변

당신이 가지고 있다고 가정

double d = 9232.129394d;

당신이 사용할 수있는 BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

또는 BigDecimal없이

d = Math.round(d*100)/100.0d;

두 솔루션 모두 d == 9232.13


답변

DecimalFormat 클래스를 사용할 수 있습니다.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));