2017-04-21 14 views
2

Oracle의 BINARY_DOUBLE과 Java의 Double은 IEEE 754 표준을 사용합니다.Oracle과 Java (IEEE 754)의 double 값 차이

그러나 정확도에는 차이가 있습니다. 예컨대 값

:

456.67d

오라클 :

declare 
    a BINARY_DOUBLE := 456.67d; 
begin 
    SYS.DBMS_OUTPUT.PUT_Line(TO_CHAR(a,'9.99999999999999999999EEEE')); 
end; 

결과 : 4.56670000000000020000E + 02

자바 :

Double d = 456.67d; 
DecimalFormat formatter = new DecimalFormat("0.000000000000000000000E000"); 
System.out.println(formatter.format(d)); 

결과 : 4.566700000000000000000E002

자바의 값은 오라클에서만큼 정확하지 않습니다.

4.56670000000000015916157281026E2

그래서 자바의 정확성에 오라클처럼 동일하지 않은 이유 :

온라인 컨버터는 456.67d에 대한 가장 정확한 표현이 있다고? 그리고 어떻게하면 Java에서보다 정확한 값을 얻을 수 있습니까?

답변

3

사용 BigDecimal :

Double d = 456.67d; 
BigDecimal bd = new BigDecimal(d); 
bd.setScale(50); 
System.out.println(bd); 
DecimalFormat formatter = new DecimalFormat("0.000000000000000000000E000"); 
System.out.println(formatter.format(bd)); 

출력 :

456.67000000000001591615728102624416351318359375 
4.566700000000000159162E002 
1

모두 정확합니다. 그들은 단지 인쇄를 위해 다른 전략을 사용합니다. >

#(
    '456.6699999999999590727384202182292938232421875' 
    '456.67000000000001591615728102624416351318359375' 
    '456.670000000000072759576141834259033203125' 
)  

그래서 어떤 진수 표현 -

d := 456.67. 
{ 
    d predecessor asFraction printShowingMaxDecimalPlaces: 50. 
    d asFraction printShowingMaxDecimalPlaces: 50. 
    d successor asFraction printShowingMaxDecimalPlaces: 50}. 

: 여기

이 스퀵 스몰 토크를 통해 인쇄 된 정확한 값입니다 (하지만 언어가 중요하지 않습니다, 그 같은 표현과 같은 연산의) (d predecessor asFraction + d asFraction)/2 printShowingMaxDecimalPlaces: 50.(d successor asFraction + d asFraction)/2 printShowingMaxDecimalPlaces: 50. 사이의 값은 동일한 부동 소수점 값 (정확한 타이는 가장 가까운 짝수로 반올림되므로 배제됩니다.이 부동 소수점은 홀수의 significand를가집니다 ...)

그래서 경계는 다음과 같습니다

#(
    '456.669999999999987494447850622236728668212890625' 
    '456.670000000000044337866711430251598358154296875' 
) 

오라클은 17 자리 숫자를 사용하여 17 두 배 정밀도 부동 소수점 값을 구별하기에 충분한 것으로 알려져 있기 때문에 더 자리 귀찮게하지 않습니다.

Java는 좀 더 영리합니다. 다음 표현 가능한 부동 소수점 값과 구별하기에 충분한 숫자를 사용합니다. 따라서 위치 17, 또는 4.5666999999999999e2에 0, 1, 2, 3 또는 4를 두는 것은 중요하지 않습니다. 여전히 부동 소수점 값입니다.