2014-02-16 4 views
1

이 문제에 대한 해결책은 필요 없습니다. 이유를 알고 싶습니다. 의 두 숫자를 보자큰 숫자를 음수로 나눌 수없는 이유는 무엇입니까? C++

#include <iostream> 
using namespace std; 

int main() 
{ 
    unsigned long long int a = 17446744073709551615; 
    signed long long int b = -30000000003; 
    signed int c; 
    c = a/b; 
    cout << "\n\n\n" << c << endl; 
} 

이제, 최근에 내가지고있어 답은 0이다. 내 long long의 크기는 8 바이트입니다. 따라서 서명되지 않은 레이블을 사용하기에 충분합니다. C 변수는 응답을 처리 할만큼 충분히 커야합니다. (Google에 따르면 -581 558 136이어야합니다.) 그래서 ... 내가 좋아하는 것

편집 내 컴퓨터에 ...

이 numeric_limits a를 사용하여 잘 -9223372036854775808의 최소 한계 내에 18,446,744,073,709,551,615와 b의 최대 withing에 떨어질 것을 지적한다.

+0

왜 그렇게 크고 의미없는 숫자가 필요합니까? http://coliru.stacked-crooked.com/a/8f7b78a46536e533 – chris

+1

제 생각에 부서는 부호없는 long long의 구분으로 이루어집니다. 즉, b는 매우 큰 부호없는 long long이됩니다. 그러므로 결과는 0입니다. – user515430

+0

'a '를'signed long long int'에 먼저 캐스트하십시오. – herohuyongtao

답변

6

로 사용 0

시도로 답변을 얻고있다.

unsigned long long int a = 17446744073709551615; 

리터럴 unsuffixed 진수 정수 타입 int, long int 또는 long long int이다; 결코 부호없는 유형의 것이 아닙니다. 그 특정 값은 long long int (2 -1)의 최대 값을 거의 확실히 초과합니다. 컴파일러가 64 비트보다 넓은 부호있는 정수형을 가지고 있지 않으면, 프로그램을 잘못 작성하게됩니다.

리터럴이 정확한 타입인지 확인하는 ULL 접미사를 추가

값은 그것이에 맞도록 2 63 -1 64 -1 (2) 사이에 우연히
unsigned long long int a = 17446744073709551615ULL; 

64 비트 부호없는 유형이지만 64 비트 서명 된 유형은 아닙니다.

(사실 그냥 U은 충분하지만,이 명시 적으로 다치게하지 않습니다.)

signed long long int b = -30000000003; 

이이 문제가되지 않습니다. 30000000003은 부호가있는 정수 유형입니다. 컴파일러가 최소 64 비트 너비 인 long long을 지원하면 오버플로가 발생하지 않습니다. 그러나만큼 당신이 a의 값에 접미사를 필요로하는, 그것은 명시 해치지 않을 것입니다 :

signed long long int b = -30000000003LL; 

을 이제 우리는이 : 분할

signed int c; 
c = a/b; 

하는 A signed long long에 의해 unsigned long long가 원인 부호가있는 피연산자는 unsigned long long으로 변환됩니다. 이 경우 변환되는 값이 음수이므로 큰 양의 값으로 변환됩니다. -30000000003unsigned long long으로 변환하면 18446744043709551613이됩니다. 1744674407370955161518446744043709551613으로 나누면 0이됩니다.

컴파일러가 64 비트보다 넓은 정수를 지원하지 않는

(대부분하지 않습니다), 당신은 -30000000003에 의해 직접 분할 17446744073709551615 할 수 없습니다 모두를 나타낼 수있는 정수 타입이 없기 때문에, 수학적으로 정확한 답변을 얻을 값. 모든 산술 연산자 (시프트 연산자 제외)에는 동일한 유형의 피연산자가 필요하며 필요에 따라 암시 적 변환이 적용됩니다.

이 경우에는 17446744073709551615ULL30000000003ULL으로 나눈 다음 부호를 설명 할 수 있습니다. (음수의 나누기에 대한 언어 규칙을 확인하십시오.)

일반적으로이 작업을 수행해야하는 경우 부동 소수점에 의존 할 수 있습니다 (즉, 정밀도가 떨어질 수 있음). 임의의 너비 정수를 사용합니다. 산술 패키지 GMP.

+0

입니다. 상당히 괜찮은 답변입니다. 아쉽게도 suffixing은 여전히 ​​0을 산출합니다. 제 컴파일러가 64 비트보다 더 넓은 범위를 지원하는지 여부는 0입니다. 하지만 그때 ... 나는 내가 놀 수있는 긴 서명되지 않은 긴 것보다 더 큰 것을 가질 계획이 아닙니다. – user3315127

0

b는 a보다 큰 부호없는 수로 처리됩니다. 따라서 당신은 당신은 대부분 불필요한 암시 적 변환의 숫자가 일어나고

c = abs(a)/abs (b) 
if ((a < 0 && b > 0) || (a> 0 && b < 0)) 
    return -c; 
return c; 
관련 문제