내가 원하는 것은 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;
반올림하려면 정확도를 뺍니다.
답변
가정 value
A는 double
, 당신은 할 수 있습니다 :
(double)Math.round(value * 100000d) / 100000d
5 자리 정밀도입니다. 0의 수는 소수의 수를 나타냅니다.
답변
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
당신을 얻을 것입니다 BigDecimal
. 그것에서 문자열을 얻으려면, 그냥 전화 BigDecimal
의 toString
방법, 또는 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));