2012-07-16 5 views
5

가능한 중복 : 자바 배정 밀도/부문


Retain precision with Doubles in java

는 자바에서이 두 작업 사이의 차이를 알고있다.

final double m1 = 11d/1e9; // gives 1.1e-8 
final double m2 = 11d * 1e-9; // gives 1.1000000000000001e-8 

생성 된 바이트 코드에서 m2의 사전 컴파일 된 결과가 이미 예상 한 결과가 아니라는 것을 알 수 있습니다. I는 다음의 값을 알 수 javap -verbose -c의 출력
는 :

const #3 = double 1.1E-8d; 
[...] 
const #6 = double 1.1000000000000001E-8d; 

I 다른 표현식에 M1 또는 M2를 사용하여, I는 동일한 결과가 없다. 나는 C에서 같은 일을하려고하면

는 M1 및 M2는 내가 곧 길이 자바를 double 정밀도로 계산을 처리하지만 난 내가 그리워 무엇인지 자신을 설명 할 수 없다 내 문제는 생각 엄격하게 1.1E-8

입니다.

답변

1

차이는 1e9가 정확히 표현 가능하고 1e-9가 정확히 표현할 수 없다는 것입니다. 작은 표현 오류로 인해 사용자가 볼 수있는 산술 오류가 발생합니다.

System.out.println(new BigDecimal(1e9)); 
System.out.println(new BigDecimal(1e-9)); 

인쇄

1000000000 
1.0000000000000000622815914577798564188970686927859787829220294952392578125E-9 

의 차이는 당신이 * 또는 /을 사용했는지하지만 당신은 하나의 경우에 정수와 다른 일부를 사용했다고하지 않습니다.

System.out.println(11 * 1e9); 
System.out.println(11 * 1e-9); 

인쇄

1.1E10 
1.1000000000000001E-8 
+0

좋아, Java에 대한 설명이지만 C에서 동일한 코드를 실행할 때 필요한 모든 정밀도가있는 이유는 무엇입니까? – Joker

+0

C 컴파일러는'javac'보다 코드를 * 많이 * 최적화 할 것입니다. 이것은 a) 더 빠르며 b) 더 정확하기 때문에 '/ 1e-9'를 '* 1e9'로 변환 할 수 있음을 의미 할 수 있습니다.Java의 컴파일러는 최적화가 거의 이루어지지 않습니다. 이는 JIT에 남아 있으며, 최적화되지 않은 최적화 된 코드가 동일한 작업을 수행해야한다는 것을 의미합니다. 그렇지 않으면 프로그램이 실행되는 동안 동작이 변경됩니다. 'double '을 String으로 변환하는 것은 C와 Java에서도 다르지만 차이점의 원인이 될 가능성은 낮습니다. 두 경우 모두 동일한 FPU를 사용합니다. –

+1

또한 C 컴파일러는 컴퓨터에있는 80 비트 부동 소수점 레지스터/계산을 사용할 수 있습니다. 이것은 플랫폼에 종속적이며 x86/x64 프로세서에서만 사용할 수 있습니다. Java는 모든 플랫폼에서 동일하게 동작하므로 80 비트 부동 소수점을 사용할 수있는 경우에만 64 비트 부동 소수점을 사용합니다. –

3

Java와 C는 차이가 없으며 둘 다 IEEE 부동 소수점 표준을 따릅니다. 유일한 차이점은 인쇄 방법이 될 수 있습니다. 정확한 숫자 1.1e-8은 double으로 표시 할 수 없습니다. 출력의 차이는 표현의 오류가 누적 된 방식과 결과를 인쇄하는 데 사용되는 반올림에 대한 세부 정보가 원인 일 수 있습니다. 아래로의 BigDecimal을 사용하는 경우

+0

네하지만 차이가 두 번째 줄 그냥 인쇄 된 임계 값을 초과 단계, 여기서 축적 얼마나 많은 오류 만의 생각 일 – Pooya

+0

9^10이 나눕니다. –

0

:

BigDecimal a=new BigDecimal(1e-9); 
BigDecimal b=new BigDecimal(11); 
System.out.println(a.multiply(b).toString()); 

당신은

1.10000000000000006850975060355784206078677556206457666121423244476318359375E-8 

JVM이 전화 번호를 반올림 전화 번호 인 것을보고로 변경됩니다

1.1000000000000001e-8 
관련 문제