문제

나는 원시 플로트가 있고 원시적 인 더블로 필요합니다. 단순히 플로트를 두 배로 던지면 이상한 정밀도가됩니다. 예를 들어:

float temp = 14009.35F;
System.out.println(Float.toString(temp)); // Prints 14009.35
System.out.println(Double.toString((double)temp)); // Prints 14009.349609375

그러나 캐스트하는 대신 플로트를 문자열로 출력하고 문자열을 더블로 구문 분석하면 원하는 것을 얻습니다.

System.out.println(Double.toString(Double.parseDouble(Float.toString(temp))));
// Prints 14009.35

문자열로 가서 돌아가는 것보다 더 좋은 방법이 있습니까?

도움이 되었습니까?

해결책

당신이 아닙니다 실제로 추가 정밀도 - 플로트가 원래 목표로했던 숫자를 정확하게 나타내지 않았다는 것입니다. 두배 ~이다 원래 플로트를 정확하게 나타냅니다. toString 이미 존재했던 "추가"데이터를 보여주고 있습니다.

예를 들어 (그리고이 숫자는 옳지 않습니다. 나는 단지 물건을 만들고 있습니다) 당신이 다음과 같이 가정 해 봅시다.

float f = 0.1F;
double d = f;

그런 다음의 가치 f 정확히 0.100000234523 일 수 있습니다. d 값이 정확히 동일한 값을 가지지 만 문자열로 변환하면 더 높은 정밀도가 정확하다는 "신뢰"하므로 일찍 둥글게하지 않으면 이미 "추가 자리"가 표시됩니다. 거기, 그러나 당신에게서 숨겨져 있습니다.

당신이 문자열로 변환하고 뒤로 변환 할 때, 당신은 원래 플로트보다 문자열 값에 더 가까운 이중 값으로 끝나고 있습니다. 그러나 그것은 단지 좋습니다. 만약에 당신은 정말로 문자열 값이 당신이 정말로 원했던 것이라고 믿습니다.

Float/Double이 여기에서 사용하기에 적합한 유형이라고 확신합니까? BigDecimal? 정확한 소수점 값 (예 : 돈)을 가진 숫자를 사용하려는 경우 BigDecimal 더 적절한 유형 IMO입니다.

다른 팁

이진 표현으로 변환하는 것이이 문제를 더 쉽게 파악할 수 있습니다.

float f = 0.27f;
double d2 = (double) f;
double d3 = 0.27d;

System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d2)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d3)));

0을 끝에 추가하여 플로트가 더블로 확장되는 것을 볼 수 있지만 0.27의 이중 표현이 '더 정확한'이므로 문제가됩니다.

   111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000

이것은 계약입니다 Float.toString(float), 부분적으로 다음과 같이 말합니다.

분수 부품 […]에 대해 몇 자리 숫자를 인쇄해야합니까? 분수 부분을 나타내려면 적어도 하나의 숫자가 있어야하며, 그 이상으로 그러나 많은 것만 인수 값을 인접한 유형 플로트 값과 고유하게 구별하는 데 필요한 더 많은 숫자. 즉, X가 유한 비 제로 인수 f에 대해이 방법에 의해 생성 된 10 진수 표현으로 표시되는 정확한 수학적 값이라고 가정합니다. 그런 다음 F는 X에 가장 가까운 플로트 값이어야합니다. 또는 두 개의 플로트 값이 X에 동일하게 가까운 경우 F는 그중 하나 여야하며 F의 유의성과 가장 중요한 비트는 0이어야합니다.

나는 오늘이 문제를 발견했으며 프로젝트가 실제로 크기 때문에 Refactor를 Bigdecimal에 사용할 수 없었습니다. 그러나 나는 해결책을 사용했다

Float result = new Float(5623.23)
Double doubleResult = new FloatingDecimal(result.floatValue()).doubleValue()

그리고 이것은 작동합니다.

Calling result.doublevalue ()는 5623.22998046875를 반환합니다

그러나 Doubleresult.doublevalue ()를 호출하면 5623.23이 올바르게 반환됩니다

그러나 나는 그것이 올바른 해결책인지 확실하지 않습니다.

a BigDecimal 대신에 float/double. 바이너리 플로팅 포인트로 표현할 수없는 숫자가 많이 있습니다 (예 : 0.1). 따라서 항상 결과를 알려진 정밀도 또는 사용으로 반올림해야합니다. BigDecimal.

보다 http://en.wikipedia.org/wiki/floating_point 자세한 내용은.

다음 해결책을 찾았습니다.

public static Double getFloatAsDouble(Float fValue) {
    return Double.valueOf(fValue.toString());
}

사용하는 경우 뜨다 그리고 더블 대신에 뜨다 그리고 더블 다음을 사용하십시오.

public static double getFloatAsDouble(float value) {
    return Double.valueOf(Float.valueOf(value).toString()).doubleValue();
}

본질적으로 부유물은 부적절하며 항상 깔끔한 반올림 "문제"가 있습니다. 정밀도가 중요하다면 소수 또는 bigdecimal을 사용하기 위해 응용 프로그램 리팩토링을 고려할 수 있습니다.

예, ON 프로세서 지원으로 인해 플로트는 소수보다 계산적으로 빠릅니다. 그러나 빠르거나 정확한 것을 원하십니까?

정보는 항목 48에 따라 제공됩니다 - 정확한 값이 필요한 경우 플로트와 두 배를 피하십시오. Joshua Bloch의 효과적인 Java 2nd Edition. 이 책은 좋은 물건으로 가득 찬 잼이며 분명히 볼만한 가치가 있습니다.

이것이 작동합니까?

float flt = 145.664454;

Double dbl = 0.0;
dbl += flt;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top