정수 나누기 : 왜 1/3 == 0의 결과입니까?


107

이 코드를 작성했습니다.

public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

결과는 0입니다.이 이유는 무엇이며이 문제를 어떻게 해결합니까?

답변:


147

두 피연산자 (1 및 3)는 정수이므로 정수 산술 (여기서 나누기)이 사용됩니다. 결과 변수를 double로 선언하면 나눗셈 후에 암시 적 변환이 발생합니다 .

물론 정수 나눗셈은 0으로 반올림 된 나눗셈의 실제 결과를 반환합니다. 따라서의 결과는 0.333...여기서 0으로 내림됩니다. (프로세서는 실제로 반올림을 수행하지 않지만 여전히 그렇게 생각할 수 있습니다.)

또한 피연산자 (숫자)가 모두 실수로 제공 되는 경우에도 유의하십시오 . 3.0 및 1.0 또는 첫 번째 , 부동 소수점 산술이 사용되어 0.333....


33
+1하고 항상 내림합니다. int i = .99999999int를 0으로 설정합니다.보다 구체적으로 정수 부분을 취하고 나머지는 버립니다.
Byron Whitlock 2011 년

37
0보다 큰 값의 경우 "아래쪽"인 "0쪽으로"반올림합니다. (+0.9는 0으로 반올림되고 -0.9는 0으로 반올림됩니다.)
Adrian Smith

@Byron : 맞아요. 분할이 매우 다르게 구현되기 때문에 프로세서가 실제로 반올림을 수행한다고 생각하지 않지만 그렇게 생각하는 것이 편리합니다.
Noldorin 2011 년

15
아니, 반올림하지 : 잘라 내기
바질 우르 큐

3
@BasilBourque 자바 용어에서 반올림DOWN 은 0을 향합니다. 반올림 FLOOR은 음의 무한대를 향합니다.
Andreas

23

1/3 양쪽이 정수이므로 정수 나눗셈을 사용합니다.

이 중 하나 이상이 float또는이 (가) 필요 double합니다.

질문과 같이 소스 코드에 값을 입력하는 경우 다음을 수행 할 수 있습니다 1.0/3. 는 1.0두 번이다.

다른 곳에서 값을받을 경우 사용할 수 (double)을 설정하는 int으로 double.

int x = ...;
int y = ...;
double value = ((double) x) / y;

10

명시 적으로 double

double g = 1.0/3.0

이것은 자바의 정수 나눗셈 연산을 사용하기 때문에 발생 1하고 3당신은 정수 상수로 입력하기 때문이다.


2

당신은 사용해야합니다

double g=1.0/3;

또는

double g=1/3.0;

정수 나누기는 정수를 반환합니다.


2

정수 나누기를하고 있기 때문입니다.

@Noldorin이 말했듯이 두 연산자가 모두 정수이면 정수 나누기가 사용됩니다.

결과 0.33333333은 정수로 나타낼 수 없으므로 정수 부분 (0) 만 결과에 할당됩니다.

연산자 중 하나가 double/ float이면 부동 소수점 산술이 수행됩니다. 하지만 그렇게하면 동일한 문제가 발생합니다.

int n = 1.0 / 3.0;

1

1과 3을 정수로 처리하므로 결과를 0으로 반올림하여 정수가됩니다.

원하는 결과를 얻으려면 숫자가 다음과 같이 두 배라는 것을 명시 적으로 Java에 알려주십시오.

double g = 1.0/3.0;

1

1을 부동으로 만들고 부동 분할이 사용되도록합니다.

public static void main(String d[]){
    double g=1f/3;
    System.out.printf("%.2f",g);
}

1

JAVA에서의 변환은 매우 간단하지만 약간의 이해가 필요합니다. 정수 연산 에 대한 JLS에 설명 된대로 :

시프트 연산자가 아닌 정수 연산자에 long 유형의 피연산자가 하나 이상 있으면 64 비트 정밀도를 사용하여 연산이 수행되고 숫자 연산자의 결과는 long 유형입니다. 다른 피연산자가 길지 않으면 먼저 숫자 승격 (§5.6)에 의해 long을 입력하도록 확장됩니다 (§5.1.5).

그리고 예제는 항상 JLS를 번역하는 가장 좋은 방법입니다.)

int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)

그렇지 않으면 32 비트 정밀도를 사용하여 연산이 수행되고 숫자 연산자의 결과는 int 유형입니다. 피연산자가 int가 아니면 먼저 숫자 승격을 통해 int를 입력하도록 확장됩니다.

short + int -> int + int -> int

Eclipse를 사용하여 두 개의를 추가하는 것조차 short쉽지 않다는 것을 보여주는 작은 예제 :

short s = 1;
s = s + s; <- Compiling error

//possible loss of precision
//  required: short
//  found:    int

이를 위해서는 정밀도가 떨어질 수있는 주조가 필요합니다.

부동 소수점 연산자도 마찬가지입니다.

숫자 연산자에 대한 피연산자 중 하나 이상이 double 유형이면 64 비트 부동 소수점 산술을 사용하여 연산이 수행되고 숫자 연산자의 결과는 double 유형 값입니다. 다른 피연산자가 double이 아닌 경우 먼저 숫자 승격 (§5.6)에 의해 double을 입력하도록 확장됩니다 (§5.1.5).

따라서 프로모션은 플로트에서 두 배로 이루어집니다.

그리고 정수와 부동 값을 혼합하면 위에서 말한 것처럼 부동 값이 생성됩니다.

이항 연산자에 대한 피연산자 중 하나 이상이 부동 소수점 유형이면 다른 하나가 정수인 경우에도 연산은 부동 소수점 연산입니다.

이항 연산자에는 해당되지만 "할당 연산자"에는 해당되지 않습니다. +=

간단한 작업 예제만으로도이를 증명할 수 있습니다.

int i = 1;
i += 1.5f;

그 이유는 여기에 암시 적 캐스트가 있기 때문입니다. 이것은 다음과 같이 실행됩니다.

i = (int) i + 1.5f
i = (int) 2.5f
i = 2

1

1과 3은 정수 상수이므로 Java는 결과가 0 인 정수 나눗셈을 수행합니다. 이중 상수를 작성하려면 1.0및 을 작성해야합니다 3.0.


1

가장 쉬운 해결책은 이렇게하는 것입니다.

double g = ((double) 1 / 3);

1.0 / 3.0을 입력하지 않았기 때문에 Java가 정수 분할이라고 가정했기 때문에 수동으로 double 데이터 유형으로 변환하고 변환 범위를 좁히는 것을 의미하더라도 그렇게 할 수 있습니다. 이것을 캐스트 연산자라고합니다.


1

나는 이걸했다.

double g = 1.0/3.0;
System.out.printf("%gf", g);

이중 계산을 수행하는 동안 .0을 사용하십시오. 그렇지 않으면 Java에서 정수를 사용한다고 가정합니다. 계산에서 임의의 양의 double 값을 사용하는 경우 출력은 double 값이됩니다. 이 모두 정수이면 출력은 정수가됩니다.


0

(1/3)은 정수 나눗셈을 의미하므로이 나눗셈에서 십진수 값을 얻을 수 없습니다. 이 문제를 해결하려면 다음을 사용하십시오.

public static void main(String[] args) {
        double g = 1.0 / 3;
        System.out.printf("%.2f", g);
    }

0
public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

1과 3은 모두 정수이기 때문에 결과는 반올림되지 않지만 잘립니다. 따라서 분수는 무시하고 정수만 취합니다.

이를 방지하려면 숫자 1 또는 3 중 하나 이상을 10 진수 형식 1.0 및 / 또는 3.0으로 지정하십시오.


0

이것을 시도하십시오 :

public static void main(String[] args) {
    double a = 1.0;
    double b = 3.0;
    double g = a / b;
    System.out.printf(""+ g);
}

코드 전용 답변을 게시하지 말고 코드가하는 일과 질문의 문제를 해결하는 방법 (및 이유)을 포함하십시오. 또한 이것은 기존의 찬성 답변이있는 8 년 된 질문이며 귀하의 답변이 기존 답변보다 가치가 있는지 여부를 고려하십시오.
Mark Rotteveel

-1

"double g = 1.0 / 3.0;" 대신.


궁금한 것뿐입니다 ...이 답변에 문제가 있습니까? 처음 문제가 발생했을 때이 방법을 사용했습니다. 이 솔루션의 문제점에 대한 설명을 주시면 감사하겠습니다. 미리 감사드립니다.
Mr. Port St Joe

@ Mr.PortStJoe 질문하는 사람에게 세부 정보를 제공하지 않습니다. 최고 평점 답변을 살펴보면 왜 그런 일이 발생하는지 설명하는 것을 볼 수 있습니다. 대답은 기술적으로 정확할 수 있지만 유용성이 제한적으로 보일 수 있습니다.
Andrew T Finnell

-1

다른 많은 사람들이 실제 문제를 지적하지 못했습니다.

정수에 대한 연산은 연산 결과를 정수로 캐스트합니다.

이것은 반드시 정수로 표시 될 수 있는 부동 소수점 결과 가 잘릴 것임을 의미합니다 (소수점 부분을 잘라 냄).

캐스트 (타입 캐스팅 / 타입 변환) 란 무엇인가요 ?

언어 구현에 따라 다르지만 Wikipedia는 상당히 포괄적 인 관점을 가지고 있으며 질문에 답하는 데 중요한 정보 인 강제 에 대해서도 이야기 합니다.

http://en.wikipedia.org/wiki/Type_conversion


이 대답은 결함이 있습니다. 1/2대상 언어 (java)가 아닌와 같은 모든 정수 분할에는 유형 변환 또는 유형 변환이 없습니다 . 정수 나누기를 호출하면 정수 결과가 생성됩니다. 유형 캐스팅 때문 만에서 최대 변환이며 intA와 double할당시.
YoYo

@YoYo 0.5가 정수라고 말하는 건가요? 나는 그렇게 생각하지 않는다, 친구.
sova

1
이 친구는에 대해 아무 말도하지 않았습니다 0.5. 간단히 말해서 Java에서는 1/2정수 나눗셈으로 0의 정수가됩니다. double에 0을 할당 할 수 있지만 0.0double 이지만 여전히 0 입니다.
YoYo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.