[java] 소수점 이하 자리를 두 배로 이동

그래서 저는 1234와 같은 이중 세트를 가지고 있습니다. 12.34로 만들기 위해 소수점 자리를 옮기고 싶습니다.

이렇게하려면 .1에서 1234를 두 번 곱합니다.

double x = 1234;
for(int i=1;i<=2;i++)
{
  x = x*.1;
}
System.out.println(x);

결과 “12.340000000000002”가 인쇄됩니다.

소수점 둘째 자리로 서식을 지정하지 않고 12.34를 올바르게 이중 저장하는 방법이 있습니까?



답변

또는를 사용하는 경우 반올림 을 사용 double하거나 float반올림 오류가 발생할 것으로 예상해야합니다. 이 작업을 수행 할 수없는 경우 BigDecimal.

문제는 0.1이 정확한 표현이 아니며 계산을 두 번 수행하면 해당 오류를 복합화한다는 것입니다.

그러나 100은 정확하게 표현할 수 있으므로 다음을 시도하십시오.

double x = 1234;
x /= 100;
System.out.println(x);

인쇄 :

12.34

이것은 Double.toString(d)사용자를 대신하여 소량의 반올림을 수행 하기 때문에 작동 하지만 많지는 않습니다. 반올림하지 않고 어떻게 생겼는지 궁금한 경우 :

System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));

인쇄물:

0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375

요컨대, 명시 적으로 수행하든 그렇지 않든 부동 소수점의 현명한 답변에 대해 반올림은 피할 수 없습니다.


참고 : x / 100그리고 x * 0.01그것은 오류를 반올림에 관해서 정확하게 동일하지 않습니다. 이는 첫 번째 표현식의 반올림 오차가 x 값에 의존하는 반면 0.01두 번째 표현식의 반올림 오차는 고정되어 있기 때문 입니다.

for(int i=0;i<200;i++) {
    double d1 = (double) i / 100;
    double d2 = i * 0.01;
    if (d1 != d2)
        System.out.println(d1 + " != "+d2);
}

인쇄물

0.35 != 0.35000000000000003
0.41 != 0.41000000000000003
0.47 != 0.47000000000000003
0.57 != 0.5700000000000001
0.69 != 0.6900000000000001
0.7 != 0.7000000000000001
0.82 != 0.8200000000000001
0.83 != 0.8300000000000001
0.94 != 0.9400000000000001
0.95 != 0.9500000000000001
1.13 != 1.1300000000000001
1.14 != 1.1400000000000001
1.15 != 1.1500000000000001
1.38 != 1.3800000000000001
1.39 != 1.3900000000000001
1.4 != 1.4000000000000001
1.63 != 1.6300000000000001
1.64 != 1.6400000000000001
1.65 != 1.6500000000000001
1.66 != 1.6600000000000001
1.88 != 1.8800000000000001
1.89 != 1.8900000000000001
1.9 != 1.9000000000000001
1.91 != 1.9100000000000001


답변

아니오-십진수 값을 정확하게 저장하려면을 사용하십시오 BigDecimal. double간단하게 할 수 있는 더 정확히 소수점 숫자의 유한 번호와 세 번째의 값을 기록 할 수있는 것보다 정확히 0.1과 같은 수를 나타냅니다.


답변

서식 지정하는 경우 printf를 시도하십시오.

double x = 1234;
for(int i=1;i<=2;i++)
{
  x = x*.1;
}
System.out.printf("%.2f",x);

산출

12.34


답변

금융 소프트웨어에서는 동전에 정수를 사용하는 것이 일반적입니다. 학교에서 부동 소수점 대신 고정 소수점을 사용하는 방법을 배웠지 만 일반적으로 2의 거듭 제곱입니다. 동전을 정수로 저장하는 것은 “고정 소수점”이라고도합니다.

int i=1234;
printf("%d.%02d\r\n",i/100,i%100);

수업 시간에 우리는 일반적으로 어떤 숫자가 밑수로 정확하게 표현 될 수 있는지 물었습니다.

들면 base=p1^n1*p2^n2어떤 N을 나타낼 수있다 .. 여기서, N = N * ^ M1 P1 P2 * ^ m2.

보자 base=14=2^1*7^1… 당신이 표현할 수 1/7 1/14 1/28 사십구분의 일하지만 1/3

금융 소프트웨어에 대해 알고 있습니다. Ticketmaster의 재무 보고서를 VAX asm에서 PASCAL로 변환했습니다. 그들은 동전에 대한 코드가있는 자체 formatln ()을 가졌습니다. 변환 이유는 32 비트 정수로는 더 이상 충분하지 않기 때문입니다. +/- 20 억 페니는 2 천만 달러이고 월드컵이나 올림픽을 위해 넘쳤습니다.

나는 비밀을 맹세했습니다. 오 잘. 아카데미에서 좋은 경우 게시합니다. 업계에서는 비밀을 유지합니다.


답변

정수 표현을 시도 할 수 있습니다.

int i =1234;
int q = i /100;
int r = i % 100;

System.out.printf("%d.%02d",q, r);


답변

이것은 컴퓨터가 부동 소수점 숫자를 저장하는 방식으로 인해 발생합니다. 그들은 정확하게 그렇게하지 않습니다. 프로그래머는 이 부동 소수점 가이드 를 읽고 부동 소수점 숫자를 처리하는 시련과 고난을 숙지 해야 합니다.


답변

많은 게시물에서 BigDecimal을 사용한다고 언급했지만 아무도 BigDecimal을 기반으로 정답을 제공하는 것을 귀찮게하지 않습니까? BigDecimal을 사용하더라도이 코드에서 알 수 있듯이 여전히 잘못 될 수 있기 때문입니다.

String numstr = "1234";
System.out.println(new BigDecimal(numstr).movePointLeft(2));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal(0.01)));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal("0.01")));

이 출력을 제공합니다.

12.34
12.34000000000000025687785232264559454051777720451354980468750
12.34

BigDecimal 생성자는 숫자 생성자보다 String 생성자를 사용하는 것이 더 낫다고 구체적으로 언급합니다. 궁극적 인 정밀도는 선택적 MathContext의 영향도받습니다.

BigDecimal의 자바 독에 따르면 이 가능 하다 BigDecimal를 만들 정확히 당신이 문자열 생성자를 사용하여 제공하는 0.1와 동일합니다.