Programing

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

lottogame 2020. 8. 27. 08:06
반응형

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


그래서 저는 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과 같은 수를 나타냅니다.


if it's just formatting, try printf

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

output

12.34

In financial software it is common to use integers for pennies. In school, we were taught how to use fixed-point instead of floating, but that is usually powers of two. Storing pennies in integers might be called "fixed point" as well.

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

In class, we were asked in general what numbers can be exactly represented in a base.

For base=p1^n1*p2^n2... you can represent any N where N=n*p1^m1*p2^m2.

Let base=14=2^1*7^1... you can represent 1/7 1/14 1/28 1/49 but not 1/3

I know about financial software -- I converted Ticketmaster's financial reports from VAX asm to PASCAL. They had their own formatln() with codes for pennies. The reason for the conversion was 32 bit integers were no longer enough. +/- 2 billion pennies is $20 million and that overflowed for the World Cup or Olympics, I forgot.

I was sworn to secrecy. Oh well. In academea, if it's good you publish; in industry, you keep it secret.


you can try integer number representation

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

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

This is caused by the way computers store floating-point numbers. They don't do so exactly. As a programmer, you should read this floating-point guide to familiarize yourself with the trials and tribulations of handling floating-point numbers.


Funny that numerous posts mention to use BigDecimal but no-one bothers to give the correct answer based on BigDecimal? Because even with BigDecimal, you can still go wrong, as demonstrated by this code

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")));

Gives this output

12.34
12.34000000000000025687785232264559454051777720451354980468750
12.34

The BigDecimal constructor specifically mentions that it is better to use String constructor than a numeric constructor. Ultimate precision is also influenced by the optional MathContext.

According to the BigDecimal Javadoc it is possible to create a BigDecimal which is exactly equal to 0.1, provided you use the String constructor.


Yes, there is. With each double operation you may lose accuracy but the amount of accuracy differs for each operation and can be minimized by choosing the right sequence of operations. For example when multiplying set of numbers, it is best to sort set by exponent before multiplying.

Any decent book on number crunching describes this. For example: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

And to answer your question:

Use divide instead of multiply, this way you get correct result.

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

No, as Java floating point types (indeed all floating point types) are a trade-off between size and precision. While they're very useful for a lot of tasks, if you need arbitrary precision, you should use BigDecimal.

참고URL : https://stackoverflow.com/questions/4937402/moving-decimal-places-over-in-a-double

반응형