Dev/Java
[Java] double 형 값의 소수점 처리
syuare
2025. 4. 21. 20:18
double형은 실수형 자료형 타입을 말하며, 소수점이 있는 실수는 대체로 double형을 통해 값을 저장한다.
이 double 형 값을 출력할 경우 소수점이 출력되는데, 소수점 끝이 0인데, 0이 그대로 출력되는 경우가 있다.
더보기

public class Main {
public static void main(String[] args) {
double result;
int a = 50000;
int b = 2;
result = (double)a/b;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("default: "+ result);
}
}

소수점 뒤에 0을 안보이게 하고 싶다.
윈도우 계산기를 보면 소수점을 처리할 때 소수점 값이 0이면 출력하지 않기에,
double형의 값을 출력할 때도 소수점 끝이 0일 경우 출력하지 않도록 하고자 한다.
먼저 가장 먼저 생각해본 것은
'다른 형으로 선언한 변수를 강제적으로 double형으로 변환하는 방법이 있으면 좋겠다.' 였다.
결론부터 얘기하면, 강제 형 변환 방법으로는 소수점 처리를 할 수 없다.
- 변수에 대해 강제 형변환을 할 수 있겠지만, 이미 선언된 변수의 자료형에 맞게 데이터 값이 반환된다.
- 즉, int형으로 계산을 했을 경우 결과 값은 int형에 맞게 반환된다.
- 이미 정수형으로 반환된 값을 double형으로 형 변환을 해도 이미 반환된 값이 정수형에 맞게 되어있기에 말이 되지 않는다.
double형을 출력할 때 내가 원하는 형식으로 변환하는 방법은 어떤 것이 있을까?
double 형으로 결과값 자료형을 선언하고, 출력 때 정수 / 실수인 것 처럼 보이게 하자
- 사용자는 프로그램에서 최종적으로 출력한 값을 확인할 수 있다.
- 출력한 값에 대한 처리는 내부 처리이고, 외부에서는 어떤 처리를 했는지 알 수 없다.
- 사용자가 기대한 형식이 있기 때문에, 그에 맞게 처리할 수 있다.
방법 1. 형식지정자 String.format()
String s = String.format("%f", v)
- 자료형이 String인 것 답게, 값을 문자열로 보여주는 형태
- 소수점은 기본적으로 6자리 고정이지만, 소수점의 자리 포맷은 별도로 설정할 수 있음
- 다만, 소수점 끝이 0이더라도 그대로 출력됨
더보기


double[] values = { 2.5, 2.0, 2.3456, 188.000, 15.0008, 1680 };
System.out.println("1) String.format()");
for (double v : values) {
// ① 기본적으로 6자리 소수점 고정 폭으로 포맷
String s = String.format("%f", v);
System.out.println(" " + s);
}

String.format()에서 소수점 끝자리 0을 제거하려면 어떻게 해야할까?
- 소수점에 있는 0을 "" 문자로 강제로 replace를 한다
- 다만, 이것을 하기 위해서는 정규식 표현을 사용해야할 수 있다.
- *정규식 표현: 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어
System.out.println("6) String.format() + regex(정규표현식)");
for (double v : values) {
// ① 기본적으로 6자리 소수점 고정 폭으로 포맷 → ② 뒤쪽 0 제거 → ③ 마침표만 남으면 제거
String s = String.format(Locale.US, "%f", v)
.replaceAll("0+$", "")
.replaceAll("\\.$", "");
System.out.println(" " + s);
}

https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D
정규 표현식 - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 노란색 강조 부분은 다음 정규식을 사용했을 때 매치된 것이다. 스티븐 클레이니는 정규 표현식의 개념을 설립한 공로자이다. 정규 표현식(正規表現式, 영어: r
ko.wikipedia.org
방법 2. DecimalFormat
DecimalFormat df = new DecimalFormat("0.######");
String s = df.format(v);
- DeciamlFormat("패턴" ) > 패턴에 따라 최대 소수점 자리를 설정할 수 있음
- 다만, 기본 코드에 패턴을 포함해야함에 따라 최대 소수점 자리를 강제로 설정해야함
- 그 외 숫자를 천 단위로 구분하는 등 다양한 포맷으로도 설정 가능함
더보기

double[] values = { 2.5, 2.0, 2.3456, 188.000, 15.0008, 1680 };
System.out.println("\n2) DecimalFormat");
DecimalFormat df = new DecimalFormat("0.######");
for (double v : values) {
System.out.println(" " + df.format(v));
}

방법 3. BigDecimal > striptrailingzeros()
BigDecimal bd = new BigDecimal(Double.toString(v))
.stripTrailingZeros();
String s = bd.toPlainString();
- stripTrailingZeros(): 소수점 끝의 0을 제거해줌
- 컴퓨터는 소수점을 표현할 때 순환 소수를 표현하지 못한다. 최대한 근사값을 표현하려고 한다.
- BigDecimal은 큰 숫자도 표현할 수 있는 타입 > IEEE 754 오차(부동소수점 오차)가 포함된 것도 안정적으로 출력함
- toPlainString(): 지수(E, 과학적 표기법) 없이 소수점 값을 출력
- BigDecimal 객체 생성 코스트가 다른 것에 비해 큼
- 코드 작성이 다른 것에 비해 복잡해질 수 있음
더보기


double[] values = { 2.5, 2.0, 2.3456, 188.000, 15.0008, 1680 };
System.out.println("\n3) BigDecimal.stripTrailingZeros()");
for (double v : values) {
BigDecimal bd = new BigDecimal(Double.toString(v))
.stripTrailingZeros();
System.out.println(" " + bd.toPlainString());
}

만약 BigDecimal 값을 출력할 때 toPlainString()을 사용하지 않으면 어떻게 될까?
double[] values = { 2.5, 2.0, 2.3456, 188.000, 15.0008, 1680 };
// 번외 BigDecimal에서 toPlainString()을 안썼을 경우
System.out.println("\n5) BigDecimal.stripTrailingZeros(), toPlainString() 사용 X");
for (double v : values) {
BigDecimal bd = new BigDecimal(Double.toString(v))
.stripTrailingZeros();
System.out.println(" " + bd);
}

방법 4. Double.toString(result);
String s = Double.toString(v);
- double값을 문자열로 변환하는 방법
- 정수 값일 경우 소수점 .0 을 제거하지 못함
- 매우 큰 수나 작은 수는 과학적 표기로 출력될 수 있음
더보기

double[] values = { 2.5, 2.0, 2.3456, 188.000, 15.0008, 1680 };
System.out.println("\n4) Double.toString()");
for (double v : values) {
System.out.println(" " + Double.toString(v));
}

예시
더보기

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
double[] values = { 2.5, 2.0, 2.3456, 188.000, 15.0008, 1680 };
System.out.println("1) String.format()");
for (double v : values) {
// ① 기본적으로 6자리 소수점 고정 폭으로 포맷
String s = String.format( "%f", v);
System.out.println(" " + s);
}
System.out.println("\n2) DecimalFormat");
DecimalFormat df = new DecimalFormat("0.######");
for (double v : values) {
System.out.println(" " + df.format(v));
}
System.out.println("\n3) BigDecimal.stripTrailingZeros()");
for (double v : values) {
BigDecimal bd = new BigDecimal(Double.toString(v))
.stripTrailingZeros();
System.out.println(" " + bd.toPlainString());
}
System.out.println("\n4) Double.toString()");
for (double v : values) {
System.out.println(" " + Double.toString(v));
}
// 번외 BigDecimal에서 toPlainString()을 안썼을 경우
System.out.println("\n5) BigDecimal.stripTrailingZeros(), toPlainString() 사용 X");
for (double v : values) {
BigDecimal bd = new BigDecimal(Double.toString(v))
.stripTrailingZeros();
System.out.println(" " + bd);
}
System.out.println("6) String.format() + regex(정규표현식)");
for (double v : values) {
// ① 기본적으로 6자리 소수점 고정 폭으로 포맷 → ② 뒤쪽 0 제거 → ③ 마침표만 남으면 제거
String s = String.format("%f", v)
.replaceAll("0+$", "")
.replaceAll("\\.$", "");
System.out.println(" " + s);
}
}
}
