이 코드 블록의 경우 :
int num = 5;
int denom = 7;
double d = num / denom;
의 값은 d
입니다 0.0
. 다음을 캐스팅하여 강제로 작동시킬 수 있습니다.
double d = ((double) num) / denom;
그러나 올바른 double
결과 를 얻는 다른 방법이 있습니까? 나는 일어날 수있는 일을 알고있는 프리미티브 캐스팅을 좋아하지 않습니다.
이 코드 블록의 경우 :
int num = 5;
int denom = 7;
double d = num / denom;
의 값은 d
입니다 0.0
. 다음을 캐스팅하여 강제로 작동시킬 수 있습니다.
double d = ((double) num) / denom;
그러나 올바른 double
결과 를 얻는 다른 방법이 있습니까? 나는 일어날 수있는 일을 알고있는 프리미티브 캐스팅을 좋아하지 않습니다.
답변:
double num = 5;
그것은 캐스트를 피합니다. 하지만 캐스트 전환은 명확하게 정의되어 있습니다. 추측 할 필요는 없으며 JLS를 확인하십시오 . int to double은 확장되는 변환입니다. §5.1.2 부터 :
확장 기본 변환은 숫자 값의 전체 크기에 대한 정보를 잃지 않습니다.
[...]
int 또는 long 값을 float로 변환하거나 long 값을 double로 변환하면 정밀도가 손실 될 수 있습니다. 즉, 값의 최하위 비트가 일부 손실 될 수 있습니다. 이 경우 결과 부동 소수점 값은 IEEE 754 반올림 모드 (§4.2.4) 를 사용하여 정수 값의 올림 된 버전이 됩니다.
5는 정확히 double로 표현 될 수 있습니다.
1.0
여전히 다른 방식으로 결과 유형이 변경됩니다. '더티 코드가 나에게 보인다'는 당신이 어떤 시나리오를 곱하는 1.0
것이 실제로 더 낫다고 생각 하는지 (또는 왜 그럴 수 있는지) 설명하지 않습니다 .
(double)num
어떻게 든 변화 한다는 잘못된 믿음 ( "변수의 유형 변경"이라고 말함) 하에서 노력하고있는 것 같습니다 num
. 그것은 아닙니다-그것은 문장의 문맥에 대해 임시 이중을 만듭니다.
캐스팅 프리미티브의 문제점은 무엇입니까?
어떤 이유로 캐스팅하고 싶지 않다면 할 수 있습니다
double d = num * 1.0 / denom;
double d = num * 1D / denom;
나는 일어날 수있는 일을 아는 프리미티브 캐스팅을 좋아하지 않습니다.
왜 프리미티브를 캐스팅하는 것에 대한 비이성적 인 두려움이 있습니까? 당신이 캐스팅 할 때 아무것도 나쁜 일이 일어날 int
A를 double
. 작동 방식을 잘 모를 경우 Java 언어 사양 에서 찾아보십시오 . 주조 int
하려면 double
A는 확대 변환 프리미티브 .
분자 대신 분모를 캐스트하여 여분의 괄호를 제거 할 수 있습니다.
double d = num / (double) denom;
double d = (double) num / denom;
... ... (이것은 우선 순위에 따라 다릅니다)
부동 소수점 Math로 연산을 수행하도록 정수의 정수 / 정수 중 하나를 캐스트합니다. 그렇지 않으면 정수 수학이 항상 선호됩니다. 그래서:
1. double d = (double)5 / 20;
2. double v = (double)5 / (double) 20;
3. double v = 5 / (double) 20;
결과를 캐스트해도 효과가 없습니다. 첫 번째 나누기는 우선 순위 규칙에 따라 수행되기 때문입니다.
double d = (double)(5 / 20); //produces 0.0
나는 당신이 생각하는 것처럼 캐스팅에 아무런 문제가 없다고 생각합니다.
double
정수 나누기에서 생성- 캐스팅 하지 않고 다른 방법은 없습니다 (명시 적으로하지는 않지만 발생할 수 있습니다).
지금, 거기에 우리가 정확한 얻는 것을 시도 할 수있는 몇 가지 방법입니다 double
값은 (여기서 num
하고 denom
있는 int
유형, 그리고 코스 주조와 ) -
명시 적 캐스팅
double d = (double) num / denom;
double d = ((double) num) / denom;
double d = num / (double) denom;
double d = (double) num / (double) denom;
하지만 double d = (double) (num / denom);
암시 적 캐스팅
double d = num * 1.0 / denom;
double d = num / 1d / denom;
double d = ( num + 0.0 ) / denom;
double d = num; d /= denom;
하지만 double d = num / denom * 1.0;
하지double d = 0.0 + ( num / denom );
오퍼레이션 랩핑을 고려할 수 있습니다. 예를 들면 다음과 같습니다.
class Utils
{
public static double divide(int num, int denom) {
return ((double) num) / denom;
}
}
이를 통해 캐스트가 원하는 것을 정확하게 수행하는지 여부를 한 번만 조회 할 수 있습니다. 이 방법은 테스트를 계속 수행하여 원하는 작업을 계속 수행 할 수 있습니다. 또한 올바른 결과를 얻는 한 나눗셈을 유발하는 데 사용하는 트릭 (여기서 답변을 사용할 수 있음)은 중요하지 않습니다. 두 정수를 나눌 필요가있는 곳이라면 어디에서나 Utils::divide
올바른 일을하고 있다고 믿을 수 있습니다 .