2013-07-30 2 views
2

이 C 코드는 음수의 절대 값을 찾으려고하지만 출력도 음수입니다. 아무도 이것을 극복 할 수있는 방법을 말해 줄 수 있습니까?64 비트 정수의 절대 값과 관련된 문제

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include <inttypes.h> 

int main() { 
    int64_t a = 0x8000000000000000; 
    a = llabs(a); 
    printf("%" PRId64 "\n", a); 
    return 0; 
} 

출력

-9223372036854775808 

UPDATE : 모든 답변

감사합니다. 나는 이것이 비표준적인 값이라는 것을 이해하며, 그 때문에 절대적인 조작을 수행 할 수 없다. 그러나 유전 프로그래밍 시뮬레이션 인 실제 코드베이스에서이 문제가 발생했습니다. 이 "유기체"는 C 표준에 대해 알지 못하고이 값을 생성한다고 주장합니다. 누군가이 문제를 해결할 효율적인 방법을 말할 수 있습니까? 다시 한번 감사드립니다.

답변

4

llabs()의 결과를 long long 유형으로 표시 할 수없는 경우 동작은 정의되지 않습니다. 이것이 여기에서 일어난다 고 추측 할 수 있습니다. 범위를 벗어난 값인 0x8000000000000000이 int64_t으로 변환 될 때 값 -9223372036854775808로 변환되고 long long 값이 64 비트이므로 값 9223372036854775808은 나타낼 수 없습니다.

프로그램이 동작을 정의하려면 llabs()에 전달 된 값이 -LLONG_MAX 이상인지 확인해야합니다. 당신이하는 일은 당신에게 달려 있습니다. "유기체"가이 값을 생성 할 수 없도록 수정하거나 (즉, 범위를 벗어나는 값을 즉시 생성 할 수없는 것들을 걸러 내십시오), 값을 전달하기 전에 클램핑하십시오 llabs().

+0

감사합니다. 나는 llabs를 호출하기 전에 잘못된 값을 특별한 경우로 검사 할 것입니다. –

1

a를, −(2^63)에서 2^63 − 10x8000000000000000 또는 −(2^63)의 절대 값을 64 비트 정수 범위 서명 2^63이며, 최대 64 비트 정수보다 크다.

4

기본적으로 할 수 없습니다. int64_t위한

표현 가능한 값의 범위는 63 -2 63 -1 +2한다. (그리고 표준은 순수의 보수 표현을 가지고 int64_t를 요구, 즉 지원되지 않는 경우, 구현은 단지 int64_t을 정의하지 않습니다.) 추가로 음의 값이 해당하는 표현 가능한 양의 값이 없다고

.

시스템의 정수 유형이 64 비트보다 큰 경우가 아니면 0x8000000000000000의 절대 값을 정수로 나타낼 수 없습니다.

실제로 프로그램의 동작은 ISO C 표준에 따라 정의되지 않았습니다. ISO C 2011 규격의 N1570 draft 섹션 7.22.6.1 인용 :

ABS, 실험실llabs 기능 정수 J의 절대 값을 계산 . 결과를 나타낼 수없는 경우 동작은 정의되지 않습니다. 그 문제

,

int64_t a = 0x8000000000000000; 

결과가 구현 정의된다. long long이 64 비트라고 가정하면 그 상수는 unsigned long long입니다. 암시 적으로 int64_t으로 변환되었습니다. 저장된 값이 -2 또는 -9223372036854775808이 될 가능성이 높지만 보장되지는 않습니다. (심지어 변환이 구현 정의 된 신호를 발생시키는 것도 허용됩니다.)

(이론적으로 프로그램의 동작이 정의되지 않고 단순하게 구현 정의 될 수 있습니다.long long이 64 비트보다 넓은 경우 llabs(a)의 평가는 정의되지 않지만 결과를 int64_t으로 변환하는 것은 구현에 따라 정의됩니다. 실제로, long long이 64 비트보다 넓은 C 컴파일러는 본 적이 없습니다.

큰 정수 값을 나타낼 필요가 있다면 GNU GMP과 같은 다중 정밀도 산술 패키지를 고려해보십시오.

2

0x8000000000000000은 부호있는 64 비트 정수로 나타낼 수있는 최소 숫자입니다. two's complement의 단점으로 인해이 값은 절대 값이 64 비트 부호있는 정수로 표시 될 수없는 유일한 64 비트 정수입니다.

이것은 0x8000000000000000 = -2^63이고, 표현 가능한 최대 64 비트 정수는 0x7FFFFFFFFFFFFFFF = 2^63-1입니다.

이 때문에 절대 값을 취하는 것은 정의되지 않은 동작이므로 일반적으로 동일한 값이됩니다.

1

최상위 비트가 높고 다른 모든 비트가 낮은 부호있는 정수는 해당 정수의 절대 값과 동일한 유형으로 나타낼 수 없습니다.

8- 비트 정수를 X = 0x80으로

int8_t 관찰; // 이진수 1000_0000, 십진수 -128

8 비트 부호있는 정수는 -128에서 +127 사이의 값을 포함 할 수 있으므로 +128 값이 범위를 벗어납니다. 16 비트 정수의 경우에도이 값이 같습니다.

int16_t = 0x8000; // 이진수 1000_0000_0000_0000, 십진수 -32,768

16 비트 정수는 -32,768과 +32,767 사이의 값을 포함 할 수 있습니다.

이 패턴은 컴퓨터의 정수에 대한 사실상의 표현처럼 2의 보수로 표현되는 한 모든 크기의 정수를 유지합니다. 2의 보수는 0을 모든 비트가 로우로, -1을 모든 비트가 하이로 유지합니다.

N 비트 부호있는 정수는 2^(N-1) -1과 2^(N-1) -1 사이의 값을 포함 할 수 있으며 부호없는 정수는 0과 2^N-1을 포함하는 값을 포함 할 수 있습니다.

관련 문제