이것은 재미있는 문제입니다.
Timons의 답변은 법적인 배수가 될 수있는 최소 정밀도를 나타내는 엡실론을 지정하는 것입니다. 응용 프로그램에서 0보다 작은 정밀도가 절대로 필요 없다는 것을 알고있는 경우.00000001 그러면 그가 제안한 것은 진실에 매우 근접한 더 정확한 결과를 얻기에 충분합니다. 최대 정밀도를 미리 알고있는 응용 프로그램에서 유용합니다. (통화 정밀도에 대한 인스턴스 금융의 경우)
그러나 근본적인 문제는 반올림을 시도 할 때 요인을 기준으로 나누면 실제로 도입됩니다. 정밀도 문제에 대한 또 다른 가능성. 복식을 조작하면 주파수 변화에 따른 부정확 한 문제가 발생할 수 있습니다. 여기에 목표는 반올림입니다
System.out.println(round((1515476.0) * 0.00001)/0.00001);
이 1499999.9999999998
가 발생합니다 : 당신은 매우 중요한 자리에서 라운드에 노력하고 특히 경우가 Timons 코드를 다음 실행하면 예를 들어 (그래서 당신의 피연산자는 < 0이다) 500000 단위로 (즉, 1500000을 원한다면)
부정확도를 제거한 유일한 방법은 BigDecimal을 통해 스케일 오프하는 것입니다. 예 :
System.out.println(BigDecimal.valueOf(1515476.0).setScale(-5, RoundingMode.HALF_UP).doubleValue());
엡실론 전략과 BigDecimal 전략을 혼합하여 사용하면 정밀도를 정밀하게 제어 할 수 있습니다. 엡실론이라는 아이디어는 당신을 매우 가깝게 만든 다음 BigDecimal은 나중에 다시 스케일 조정하여 발생하는 부정확성을 제거합니다. BigDecimal을 사용하면 응용 프로그램의 예상 성능이 저하되지만
최종 분할에서 오류를 다시 입력 할 수있는 입력 값이 없다는 것을 결정할 수있는 경우에는 크기 조정을 위해 BigDecimal을 사용하는 마지막 단계가 항상 필요한 것은 아니라는 점이 지적되었습니다. 현재 나는 이것을 어떻게 적절히 결정할 수 있을지 모르겠다. 그래서 누군가가 어떻게 그것에 대해 듣고 기뻐할 지 안다면.
부동 소수점 산술 오류를 모두 피할 수는 없습니다. 숫자를 나타내는 데 사용되는 비트 수는 항상 유한합니다. 당신이 할 수있는 것은 더 높은 정밀도 (비트)를 가진 데이터 타입을 사용하는 것입니다. –
사실입니다. 내 대답을 편집하여 BigDecimal의 사용을보다 정확하게 반영 할 것입니다. –
BigDecimal_division_가 +, -, *와 다르게 취급되어야한다는 메모를 추가하겠습니다. 기본적으로 정확한 값 (1/3 등)을 반환 할 수 없으면 예외가 발생하기 때문입니다. 비슷한 상황에서 BigDecimal.valueOf (a) .divide (BigDecimal.valueOf (b), 25, RoundingMode.HALF_UP) .doubleValue() 여기서 25는 정밀도의 최대 자릿수 (double 결과에서 필요한 것 이상). –