0과 -0을 구별 할 수 있습니까?


94

정수 값 0-0본질적으로 동일 하다는 것을 알고 있습니다. 하지만 구분이 가능한지 궁금합니다.

예를 들어, 변수가 할당되었는지 어떻게 알 수 -0있습니까?

bool IsNegative(int num)
{
    // How ?
}

int num = -0;
int additinon = 5;

num += (IsNegative(num)) ? -addition : addition;

-0이 메모리에 저장되는 것과 똑같은 방식으로 저장 0됩니까?


9
정수의 경우 차이가 없습니다.
Maroun 2015-04-30

14
이은 구현에 따라서 다릅니다 만, 구현에 대한 int2의 보수에서 (지금까지 가장 일반적으로 발생으로) 표현, 0그리고 -0동일한 비트 표현이있다.
Mankarse 2015

11
2의 보수 기계에서는 비트 수준에서 차이가 없습니다.
Marco A.

17
@VirtualSnake : "in binary"는 무엇을 의미합니까? 있다, 사실, 바이너리 인코딩은 거기에 있다 로그인과 크기 사이 -0 0으로, 예를 들어 구분.
Benjamin Lindley 2015

8
@VirtualSnake 맞습니다, 우리는에 대해 이야기하고 int있습니다. Ones의 보완 인코딩을 참조하십시오 .
CiaPan 2015

답변:


112

대상 머신에 따라 다릅니다.

정수에 2의 보수 표현 을 사용하는 컴퓨터에서는 비트 수준 에서 0-0(동일한 표현을 가짐) 간에 차이없습니다.

당신의 기계가 1의 보수를 사용했다면 , 당신은 확실히 할 수 있습니다

0000 0000   -> signed01111 1111   -> signed   0

분명히 우리는 기본 지원을 사용 하는 것에 대해 이야기하고 있습니다 . x86 시리즈 프로세서는 부호있는 숫자의 두 가지 보완 표현을 기본 지원합니다. 다른 표현을 사용하는 것은 확실히 가능하지만 효율성이 떨어지고 더 많은 지침이 필요합니다.

(JerryCoffin도 언급했듯이 : 1의 보수가 대부분 역사적 이유로 고려 되었음에도 불구하고 부호있는 크기 표현 은 여전히 ​​상당히 일반적이며 음수 및 양수 0에 대한 별도의 표현을 가지고 있습니다)


6
@TobiMcNamobi : 걱정할 것 같지 않습니다. 누군가가 그러한 기계에 대한 출력을 생성하기 위해 C ++ 컴파일러를 이식하는 것을 귀찮게 해본 적이 있다면 놀랄 것입니다.
Benjamin Lindley 2015

1
저는 Benjamin의 의견에 동의합니다. 역사적 으로 그것을 사용하는 기계가 있었지만 요즘에는 그것을 사용하는 생산 기계를 알지 못합니다. 그럼에도 불구하고 항상 알고 기억하는 것이 좋습니다.
Marco A.

4
@TobiMcNamobi의 1의 보수는 유니시스 2200 시스템에서 사용하기에 아직 stackoverflow.com/a/12277974/995714의 stackoverflow.com/q/6971886/995714
phuclv

2
나는 1의 보수 요구 사항 보았다 적이 - 않는 표준은 실제로 보증이 0하고 -0있는 다른 ? 솔직히 같은 값의 두 비트 표현을 허용하는 것과 비슷하게 작동 할 것으로 예상했을 것이며 프로그램은 어떤 것이 든 사용할 수 있습니다.

8
@Hurkly : 아니오, 음의 0 표현이 존재하더라도 표준은 표현식을 사용하는 할당 또는 초기화 -0, 즉 -정수 상수에 단항 연산자를 적용한 결과 가 음의 0 표현임을 보장하지 않습니다 0. 에 관계없이 표현의 표준 말한다 결코 0-0네거티브 제로 비트 패턴이있을 수 있습니다 만 것을 수학적으로 다른 값입니다. 있는 경우 여전히 동일한 숫자 값인 0을 나타냅니다.
Steve Jessop 2015

14

에 대한 int(거의 보편적 인 "2의 보수"표현)의 표현 0-0동일합니다. (예 : IEEE 754 부동 소수점과 같은 다른 숫자 표현에서는 다를 수 있습니다.)


9
>> 2의 보수 표현 가정
Marco A.

12

2의 보수에서 0을 나타내는 것으로 시작하겠습니다 (물론 다른 많은 시스템과 표현이 있습니다. 여기서는이 특정 시스템을 참조합니다). 8 비트, 0은 다음과 같다고 가정합니다.

0000 0000

이제 모든 비트를 뒤집고 1을 더하여 2의 보수를 얻습니다.

1111 1111 (flip)
0000 0001 (add one)
---------
0000 0000

우리는를 얻었고 0000 0000그것은 -0의 표현이기도합니다.

그러나 1의 보수에서 부호있는 0은 0000 0000이지만 -0은 1111 1111입니다.


1
내 답변을 개선하기 위해 왜 반대표를 던 졌는지 알 수 있습니까?
Maroun 2015-04-30

1
대부분의 다른 답변은 기술적으로 정확하지만 답변은 실용적이며 구현을 제공합니다. 좋은.
umlcat 2015 년

9

나는 C와 C ++ 구현이 일반적으로 밀접하게 관련되어 있기 때문에이 대답을 남겨두기로 결정했지만 실제로 생각했던 것처럼 C 표준을 따르지 않습니다. 요점은 C ++ 표준이 이와 같은 경우에 어떤 일이 발생하는지 지정하지 않는다는 것입니다. 또한 2로 보완되지 않은 표현은 현실 세계에서 매우 드물고, 존재하는 곳에서도 다른 사람이 쉽게 발견 할 수있는 것으로 드러내 기보다는 많은 경우에 차이를 숨기는 경우가 많습니다.


존재하는 정수 표현에서 음수 0의 동작은 C 표준 에서처럼 C ++ 표준에서 엄격하게 정의되지 않습니다. 그러나 C 표준 (ISO / IEC 9899 : 1999)을 최상위 수준의 표준 참조로 인용합니다 [1.2].

C 표준 [6.2.6.2]에서 음의 0은 비트 연산의 결과이거나 음의 0이 이미 존재하는 연산 (예 : 음의 0을 값으로 곱하거나 나누거나 0)-단항 빼기 연산자를 예에서와 같이 일반 0 값에 적용하면 일반 0이 보장됩니다.

음의 0을 생성 할 수 있는 경우 에도 음의 0을 지원하는 시스템에서도 그럴 것이라는 보장은 없습니다.

이러한 경우가 실제로 음의 0을 생성하는지 일반 0을 생성하는지, 음의 0이 객체에 저장 될 때 일반 0이되는지는 지정되지 않습니다.

따라서 우리는 결론을 내릴 수 있습니다. 아니오,이 경우를 감지 할 수있는 신뢰할 수있는 방법이 없습니다. 2가 아닌 보완 표현이 현대 컴퓨터 시스템에서 매우 드물다는 사실이 아니더라도.

C ++ 표준은 "음의 0"이라는 용어를 언급하지 않으며, 허용되는 [3.9.1 para 7]을 제외하고는 부호있는 크기와 1의 보수 표현에 대한 세부 사항에 대해 거의 논의하지 않습니다.


일반적으로 아니요, C에서 어떤 것이 참 / 필수적이라는 사실이 반드시 C ++에서 참 / 필수임을 의미 하지는 않습니다 . C가 규범 적 참조라는 사실은 C ++가 여러 가지 (주로 표준 헤더의 내용)에 대한 C 표준을 참조하지만 정수 유형의 정의는 그런 것 중 하나가 아님을 의미합니다. 그러나 음의 0을 생성하는 보장 된 방법이 없다는 것은 결론이 여전히 사실임을 의미하며, 표현이 존재하더라도 산술을 사용하여 1을 생성 할 확실한 방법이 없음을 의미합니다.
Steve Jessop 2015

그렇다면 왜 C ++ 표준이 이와 같은 것에 대해 훨씬 덜 상세하게 들어가는 것일까 요?
Random832 2015

1
개인적 취향에 따라 C ++ 표준에 투표하는 사람의 수가 "개인적"인 것으로 간주 될 수 있다면 :-) 정의에 대해 C 표준을 따르려고한다면 적절한 작업을 수행 할 수 있습니다. 다른 경우와 마찬가지로 세부 사항을 포함 하지 않습니다 .
Steve Jessop 2015

"C ++는 ISO / IEC 9899 : 1999 프로그래밍 언어 — C (이하 C 표준이라고 함)에 설명 된대로 C 프로그래밍 언어를 기반으로하는 범용 프로그래밍 언어입니다." [1.1 para 2] 규범적인 의미가 있습니까? 나는 그것이 일반적으로 C ++ 표준에 의해 특별히 재정의되지 않은 것에 대해 C 표준을 통합하기위한 것이라고 생각했습니다.
Random832 2015

Random832 아니요의 단지 역사 노트 @ (예를 들어, 거기에, 아니 _Bool하거나 _Complex또는 지정된 이니셜 라이저 또는 C 복합 리터럴 ++). C ++ 표준은 원하는 경우 C 표준을 통합하는 방법을 알고 있습니다. 예 : [basic.fundamental] / p3 : "부호있는 정수 유형과 부호없는 정수 유형은 C 표준, 섹션 5.2.4.2.1에 주어진 제약 조건을 충족해야합니다."
TC

8

컴퓨터에 -0+0에 대한 고유 한 표현이 있으면 memcmp구분할 수 있습니다.

패딩 비트가있는 경우 실제로 0이 아닌 값에 대한 여러 표현이있을 수 있습니다.


5

C ++ 언어 사양에는 음의 0 과 같은 int가 없습니다 .

이 두 단어가 갖는 유일한 의미는 3 더하기 5 가 and에 적용된 이항 연산자 인 것처럼 단항 연산자가 -적용됩니다 .0+35

뚜렷한 음의 0 이있는 경우 , 2의 보수 (정수 유형의 가장 일반적인 표현)는 두 가지 형태의 0을 표현할 방법이 없기 때문에 C ++ 구현에 대해 불충분 한 표현입니다.


반대로, 부동 소수점 (IEEE 이후)에는 별도의 양수 및 음수 0이 있습니다. 예를 들어 1을 1로 나눌 때 구별 할 수 있습니다. 양의 0은 양의 무한대를 생성합니다. 음수 0은 음의 무한대를 생성합니다.


그러나 int 0 (또는 임의의 int 또는 다른 유형의 다른 값)의 다른 메모리 표현이있는 경우 다음 memcmp을 발견하는 데 사용할 수 있습니다 .

#include <string>

int main() {
    int a = ...
    int b = ...
    if (memcmp(&a, &b, sizeof(int))) {
        // a and b have different representations in memory
    }
}

물론 이것이 발생하면 직접 메모리 작업 외에 두 값은 여전히 ​​똑같은 방식으로 작동합니다.


3
사실, 그 존재를 요구하지 않는 언어가 그 존재를 요구하지 않는다는 의미는 아닙니다. 힌트 : 둘 다 요구하지 않습니다.
Deduplicator

2
@Deduplicator, 일종의. "C ++ 언어"는 "C ++ 언어 사양 "을 의미합니다. 스펙에 프 루비 네이터에 대한 언급도 없기 때문에 너무 모호하지 않고 "C ++에는 프 루비 네이터가 없습니다"라고 말할 수 있습니다. 분명하다고 생각했지만 개선하겠습니다.
Paul Draper

1
언어 사양에는 유니콘도 언급되어 있지 않습니다.
ypercubeᵀᴹ

2

단순화하기 위해 시각화하는 것이 더 쉽다는 것을 알았습니다.

유형 int (_32)는 32 비트로 저장됩니다 . 32 비트는 2 ^ 32 = 4294967296 고유 값을 의미 합니다 . 따라서 :

unsigned int 데이터 범위는 0 ~ 4,294,967,295입니다.

음수 값의 경우 저장 방법에 따라 다릅니다. 경우에

의 경우에는 하나의 보수 값 -0 존재한다.


2
나는 하향 표를하지 않았지만 현재 int32 비트에 저장되지 않은 플랫폼이 더 인기가 있습니다.
Maciej Piechotka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.