왜 0이 거짓입니까?


115

이 질문은 멍청하게 들릴지 모르지만, 0평가 false및 기타 [정수] 값 true이 대부분의 프로그래밍 언어에 대한 이유는 무엇입니까?

문자열 비교

질문이 너무 간단 해 보이기 때문에 좀 더 설명해 드리겠습니다. 무엇보다도 프로그래머에게 분명해 보일 수 있지만 프로그래밍 언어가없는 이유는 무엇입니까? 나는 어디에서 0평가 true하고 다른 모든 [정수] 값을 false? 그 말은 무작위로 보일지 모르지만, 좋은 생각이었던 몇 가지 예가 있습니다. 우선, 문자열의 3 방향 비교 strcmp를 예로 들어 보겠습니다. 저는 C 를 예로 들어 보겠습니다. C를 모국어로 사용하는 프로그래머라면 다음 코드를 작성하려고 할 수 있습니다.

if (strcmp(str1, str2)) { // Do something... }

문자열이 같을 때 평가되는 strcmp반환 0값 때문에 false, 초보 프로그래머가 시도한 것은 비참하게 실패하고 일반적으로 처음에 이유를 이해하지 못합니다. 더라면 0으로 평가 true하는 대신,이 기능은 가장 간단한 표현에 사용 된 수 - 위의 한 - 지 어떤지를 비교, 그리고에 대한 적절한 검사 때 -11필요한 경우에만 수행되었을 것입니다. 우리는 대부분의 경우 반환 유형을 bool(마음 속으로) 생각했습니다.

또한,의 새로운 유형을 소개하자 sign, 그건 그냥 값을 사용합니다 -1, 0하고 1. 꽤 편리 할 수 ​​있습니다. C ++에 우주선 연산자 가 있고 그것을 원한다고 상상해보십시오 std::string(글쎄, 이미 compare기능이 있지만 우주선 연산자가 더 재미 있습니다). 선언은 현재 다음과 같습니다.

sign operator<=>(const std::string& lhs, const std::string& rhs);

0에 대한 평가를 받았다 면 true, 우주선 연산자는 존재하지 않았을 것이며, 우리는 operator==그런 식으로 선언 할 수있었습니다 .

sign operator==(const std::string& lhs, const std::string& rhs);

이것은 operator==한 번에 3 방향 비교를 처리했을뿐 아니라, 다음과 같은 점검을 수행하는 데 여전히 사용될 수 있습니다.

if (str1 == str2) { // Do something... }

오래된 오류 처리

이제 예외가 있으므로이 부분은 그러한 언어가 존재하지 않는 구 언어에만 적용됩니다 (예 : C). C의 표준 라이브러리 (및 POSIX 라이브러리)를 보면 0성공하면 maaaaany 함수가 반환 되고 그렇지 않으면 정수가 반환되는지 확인할 수 있습니다 . 슬프게도 일부 사람들이 이런 종류의 일을하는 것을 보았습니다.

#define TRUE 0
// ...
if (some_function() == TRUE)
{
    // Here, TRUE would mean success...
    // Do something
}

프로그래밍에서 어떻게 생각하는지 생각하면 종종 다음과 같은 추론 패턴이 있습니다.

Do something
Did it work?
Yes ->
    That's ok, one case to handle
No ->
    Why? Many cases to handle

우리가 다시 생각해 보면, 그것은 유일한 중립 값을 넣어 감각을 만들었을 것입니다 0,에을 yes(그것은 C의 기능이 작동 방법) 다른 모든 값이 될 수있는의 많은 경우를 해결하는 동안, no. 그러나 내가 아는 모든 프로그래밍 언어 (아마도 실험적인 esotheric 언어는 제외) 는 조건 에서 yes평가되는 반면 모든 경우는로 평가됩니다 . "작동"이 하나의 사례를 나타내는 반면 "작동하지 않는"은 많은 가능한 원인을 나타내는 많은 상황이 있습니다. 우리가 그렇게 생각한다면, 평가 하고 나머지 는 훨씬 더 의미가있을 것입니다.falseifnotrue0truefalse

결론

여기서 왜 우리가 언어를 설계 않은 : 내 결론은 본질적으로 내 원래의 질문 0입니다 false, 다른 값은 true내 몇 가지 예 위 어쩌면 내가 좀 더 생각하지 않았다 계정에 복용?

후속 조치 : 많은 아이디어와 그에 대한 가능한 많은 이유가있는 많은 답변이 있음을 알게되어 기쁩니다. 나는 당신이 그것에 대해 얼마나 열정적 인 것 같아요. 나는 독창적 으로이 질문을 지었지만, 당신이 너무 열정적으로 보였으므로 조금 더 나아가서 Math.SE 에서 0과 1의 부울 선택의 근거 에 대해 질문 했습니다. :)


32
strcmp()3 개의 다른 값을 반환하므로 true 또는 false의 좋은 예는 아닙니다. 쉘 사용을 시작할 때 놀랍니다. 여기서 0은 true를 의미하고 다른 것은 false를 의미합니다.
ott--

52
@ ott-- : 유닉스 쉘에서 0은 성공을 의미 하고 0이 아닌 것은 실패를 의미합니다. "true"와 "false"와 같은 것은 아닙니다.
Keith Thompson

14
@KeithThompson : Bash (및 기타 쉘)에서 "성공"및 "실패"는 실제로 "true"및 "false"와 동일합니다. 예를 들어, 다음과 같은 명령문을 고려하십시오. if true ; then ... ; fiwhere where true0을 리턴하는 명령이며이를 if실행 ...합니다.
ruakh

13
하드웨어에는 부울이없고 이진 숫자 만 있으며 대부분의 역사적 ISA에서는 0이 아닌 숫자가 모든 조건 분기 명령에서 "true"로 간주됩니다 (대신에 플래그를 사용하지 않는 한). 따라서 저수준 언어는 반드시 기본 하드웨어 속성을 따라야합니다.
SK-logic

2
@MasonWheeler 부울 타입이 있다고해서 아무 의미가 없습니다. 예를 들어 파이썬은 하지bool유형 만 비교 / 조건 등이 가질 수있는 경우 반환 값을.
Bakuriu

답변:


98

0이다 false그들은 공통점이 모두 제로 요소이기 때문에 semirings을 . 그것들은 별개의 데이터 타입이지만, 동형 대수 구조에 속하기 때문에 그것들 사이를 변환하는 것은 직관적 인 의미가 있습니다.

  • 0덧셈에 대한 항등식이고 곱셈에 대해서는 0입니다. 이것은 IEEE-754 부동 소수점 숫자가 아닌 정수 및 유리수에는 적용 됩니다 : 0.0 * NaN = NaN0.0 * Infinity = NaN.

  • false부울 xor (⊻) 의 ID이며 부울 (∧)의 경우 0입니다 . 부울이 정수 모듈로 2 인 {0, 1}로 표시되면 캐리없이 ⊻를 곱셈으로 ∧를 생각할 수 있습니다.

  • ""[]연결에 대한 정체성이 있지만, 그들이 0으로 의미가있는 몇 가지 작업이 있습니다. 반복은 하나이지만 반복과 연결은 배포되지 않으므로 이러한 작업은 반올림을 형성하지 않습니다.

이러한 암묵적인 변환은 소규모 프로그램에서는 도움이되지만 대규모에서는 프로그램을 추론하기가 더 어려워 질 수 있습니다. 언어 디자인의 많은 장단점 중 하나 일뿐입니다.


1
당신이 목록을 언급 한 것이 반갑습니다. (BTW, Common Lisp nil의 빈 목록 []이자 false값입니다. 다른 데이터 유형의 ID를 병합하는 경향이 있습니까?) 여전히 가산 성 ID로 허위로 간주하고 승수 정체성으로 참으로 간주하는 것이 왜 자연스러운 지 설명해야합니다. 그리고 다른 방법은 아닙니다. true로 식별 AND하고 0 으로 간주 할 수 OR없습니까?
조르지오

3
유사한 신원을 나타내는 +1 마지막으로 "컨벤션, 처리"로 넘어 가지 않는 대답입니다.
l0b0

5
구체적인 세부 사항과 아주 오래된 수학을주는 일이있는이 이어되었으며 긴 의미했다
지미 호파를

1
이 대답은 말이되지 않습니다. true또한 반올림의 식별 및 0입니다 (부울 및 / 또는). 고려할만한 Appart Convention false은 0보다 가까운 이유가 없습니다 true.
TonioElGringo

1
@TonioElGringo : true와 false의 차이는 XOR과 XNOR의 차이입니다. AND / XOR를 사용하여 동형 고리를 형성 할 수 있습니다. 여기서 true는 곱셈 동일성이고 가산 성 허위입니다. 또는 OR 및 XNOR에서 false는 곱셈 동일성이고 true는 가산 성입니다. 그러나 XNOR은 일반적으로 공통으로 간주되지 않습니다 XOR과 같은 기본적인 작동.
supercat

74

수학이 효과가 있기 때문입니다.

FALSE OR TRUE is TRUE, because 0 | 1 is 1.

... insert many other examples here.

전통적으로 C 프로그램에는 다음과 같은 조건이 있습니다.

if (someFunctionReturningANumber())

오히려

if (someFunctionReturningANumber() != 0)

0과 거짓이라는 개념은 잘 이해되어 있기 때문입니다.


21
수학은 의미가 있기 때문에 언어는 그렇게 설계되었습니다. 그게 먼저 왔습니다.
Robert Harvey

26
@ Morwenn, 그것은 19 세기와 George Boole로 거슬러 올라갑니다. 사람들은 컴퓨터보다 오랫동안 False를 0으로, True를! 0으로 표현했습니다.
Charles E. Grant

11
AND가 +이고 OR이 *가되도록 모든 정의를 변경하기 만하면 수학이 다른 방식으로 작동하지 않는 이유를 알 수 없습니다.
Neil G

7
정확히 : 수학은 두 가지 방식으로 작동하며이 질문에 대한 답은 순수하게 일반적인 것 같습니다.
Neil G

6
@Robert 게시물에 "수학적 토대"를 입력 할 수 있다면 좋을 것입니다.
phant0m 2016 년

38

다른 사람들이 말했듯이, 수학이 먼저 나왔습니다. 이것이 0은 false1이고 1은 true입니다.

우리는 어떤 수학에 대해 이야기하고 있습니까? 디지털 컴퓨터가 등장하기 오래 전인 1800 년대 중반부터 시작된 부울 대수 .

또한이 규칙은 부울 대수보다 오래된 제안 논리 에서 나왔다고 말할 수 있습니다 . 이것은 프로그래머가 알고 사랑 논리적 결과 (많은의 형식화이다 false || x동일 x, true && x동일 x등).

기본적으로 우리는 두 가지 요소가있는 집합에 대한 산술에 대해 이야기하고 있습니다. 이진수로 계산하는 것을 고려하십시오. 부울 대수는이 개념의 기원과 이론적 토대입니다. C와 같은 언어의 규칙은 간단한 응용 프로그램입니다.


2
당신은 확실히 할 수 있습니다. 그러나 "표준"방식으로 유지하면 일반적인 산술 (0 + 1 = 1이 아니라 0 + 1 = 1)에 적합합니다.
joshin4colours

2
예, 그러나 정의를 반대로 바꾸면 아마도 AND로 +와 OR로 *를 쓸 것입니다.
Neil G

3
수학은 먼저 오지 않았다. 수학은 0과 1이 AND를 곱셈과 같고 OR이 덧셈과 같은 필드를 형성한다는 것을 인식했습니다.
Kaz

1
@Kaz : 그러나 OR 및 AND가있는 {0, 1}은 필드를 형성하지 않습니다.
조르지오

2
그것은 더 많은 답변과 의견이 그렇게 말하는 것을 조금 귀찮게합니다 true = 1. true != 0정확히 동일하지 않기 때문에 정확하지 않습니다. 왜 하나와 같은 비교를 피해야하는지 한 가지 이유 (단 하나만이 아님) if(something == true) { ... }.
JensG

26

나는 이것이 전자 제품의 "상속"과 관련이 있다고 생각했고

  • 0= off, negative, no,false
  • 1= on, positive, yes,true

문자열이 같으면 구현과 관련이있을 때 strcmp 는 0을 반환합니다. 실제로 두 문자열 사이의 "거리"를 계산하기 때문입니다. 0도 거짓으로 간주되는 것은 우연의 일치 일뿐입니다.

이 경우 0은 오류가 없음 을 의미하는 데 사용되며 다른 숫자는 오류 코드 이므로 성공시 0반환 하는 것이 좋습니다. 하나의 성공 코드 만 있고 여러 오류 코드를 가질 수 있으므로 다른 숫자를 사용하여 성공하는 것은 의미가 없습니다. "작동 했습니까?" if 문 식과 0 = yes라고 말하면 더 의미가 있지만식이 더 정확합니다. "문제가 있습니까?" 그러면 0 = 아니오가 의미가 있음을 알 수 있습니다. 여기서 생각하는 false/true것은 실제로 의미가 없습니다 no error code/error code.


하하, 당신은 반환 오류 질문을 명시 적으로 언급 한 첫 번째 사람입니다. 나는 이미 내가 그것을 내 자신의 방식으로 해석하고 다른 방법으로 물을 수 있다는 것을 알고 있었지만, 당신은 그것을 명시 적으로 표현한 첫 번째 사람입니다 (많은 답변과 의견 중). 실제로, 나는 하나 또는 다른 방법은 의미가 없다고 말하고 싶지만, 둘 다 다른 방식으로 의미가 있습니다 :)
Morwenn

1
사실은 내가 말하고 싶지만 0위해 success/no error다른 정수 오류 코드를 나타냅니다 때 의미가있는 유일한 일이다. 우리가 여기서 참이나 거짓에 대해 전혀 이야기하지 않기 때문에 다른 경우 0에도 그 사실 을 나타내는 false것은 중요하지 않습니다.)
Svish

나는 같은 생각을
가졌기

1
strcmp()거리 계산에 대한 요점 은 꽤 좋습니다. 가 호출 되었다면 strdiff()다음 if (!strdiff())매우 논리적 일 것입니다.
케빈 콕스

"electronics [...] 여기서 0 = [...] false, 1 = [...] true"-전자 제품의 경우에도 이것은 규칙 일 뿐이며 유일한 것은 아닙니다. 이 포지티브 로직을 호출하지만 포지티브 전압은 false를, 음의 값은 true를 나타내는 음의 로직을 사용할 수도 있습니다. 그런 다음 AND에 사용하는 회로는 OR이되고 OR은 AND가됩니다. De Morgan의 법칙으로 인해 모든 것이 동등합니다. 때로는 편의를 위해 전자 회로의 일부를 음의 논리로 구현하여 해당 부분의 신호 이름이 그 위에 막대로 표시되는 경우가 있습니다.
Jules

18

설명한 바와 같이 ,이 문서 의 값 false과는 true정수 0과 1과 혼동하지 않아야하지만, 두 개의 요소 (볼의 갈루아 필드 (유한 필드)의 구성 요소로 식별 될 수있다 여기에서 ).

필드는 특정 공리를 만족시키는 두 가지 작업으로 구성된 집합입니다.

실수 0은 또한 숫자가 숫자 0과 1 인 필드 (유한 숫자는 아님)이기 때문에 필드의 가산 성 및 곱셈 ID를 나타내는 데 일반적으로 사용됩니다.

덧셈 동일성은 모든 x에 대해 필드의 요소 0입니다.

x + 0 = 0 + x = x

곱하기 동일성은 모든 x에 대해 필드의 요소 1입니다.

x * 1 = 1 * x = x

두 요소의 유한 필드는이 두 요소, 즉 가산 성 0 (또는 false)과 곱셈 성 1 (또는 true) 만 갖습니다 . 이 필드의 두 가지 조작은 논리 XOR (+) 및 논리 AND (*)입니다.

노트. 연산을 뒤집 으면 (XOR은 곱셈이고 AND는 덧셈입니다) 곱셈은 덧셈에 대해 분배되지 않으며 더 이상 필드가 없습니다. 이 경우 두 요소 0과 1을 어떤 순서로든 호출 할 이유가 없습니다. 또한 XOR 대신 연산 OR을 선택할 수 없습니다. OR / AND를 덧셈 / 곱셈으로 해석하는 방법에 관계없이 결과 구조는 필드가 아닙니다 (필드의 공리에 필요한 모든 역 요소가있는 것은 아닙니다).

C 함수에 관하여 :

  • 많은 함수가 오류 코드 인 정수를 반환합니다. 0은 오류 없음을 의미합니다.
  • 직관적으로이 함수 strcmp는 두 문자열의 차이를 계산합니다. 0은 두 문자열 사이에 차이가 없음을 의미합니다. 즉 두 문자열이 동일합니다.

위의 직관적 인 설명은 반환 값의 해석을 기억하는 데 도움이 될 수 있지만 라이브러리 설명서를 확인하는 것이 더 쉽습니다.


1
+1 : 임의로 바꾸면 수학이 더 이상 해결되지 않습니다.
지미 호파

2
뒤집힘 : 두 개의 요소와 연산 * 및 +가있는 필드가 주어지면 0으로 True를 식별하고 1로 False를 식별합니다. *로 OR을 식별하고 +로 XOR을 식별합니다.
Neil G

1
이러한 식별은 모두 동일한 필드에서 수행되며 둘 다 부울 논리 규칙과 일치합니다. 귀하의 메모는 불행히도 잘못되었습니다 :)
Neil G

1
True = 0이고 XOR이 +라고 가정하면 True는 XOR의 ID 여야합니다. 그러나 True XOR True = False이기 때문이 아닙니다. True에서 XOR 연산을 다시 정의하지 않으면 True XOR True = True가됩니다. 그런 다음 방금 이름을 바꿨 기 때문에 구성이 작동합니다 (수학적 구조에서는 항상 성공적으로 이름을 바꾸고 동형 구조를 얻을 수 있습니다). 반면, True, False 및 XOR의 일반적인 의미를 가지게되면 True XOR True = False 및 True는 부가적인 동일성이 될 수 없습니다. 즉, True는 0
Giorgio

1
@Giorgio : 나는 나의 마지막 코멘트에서 당신의 코멘트에 따라 나의 구성을 수정했습니다…
Neil G

13

대체 시스템도 수용 가능한 설계 결정이 될 수 있음을 고려해야합니다.

쉘 : 0 종료 상태가 true, 0이 아닌 값이 false

0 종료 상태를 true로 처리하는 쉘의 예는 이미 언급되었습니다.

$ ( exit 0 ) && echo "0 is true" || echo "0 is false"
0 is true
$ ( exit 1 ) && echo "1 is true" || echo "1 is false"
1 is false

이론적으로는 성공할 수있는 한 가지 방법이 있지만 실패 할 수있는 많은 방법이 있으므로 "오류 없음"을 의미하는 특수 값으로 0을 사용하는 것은 실용적입니다.

루비 : 0은 다른 숫자와 같습니다

"일반적인"프로그래밍 언어 중에는 Ruby와 같이 0을 실제 값으로 취급하는 특이 치가 있습니다.

$ irb
irb(main):001:0> 0 ? '0 is true' : '0 is false'
=> "0 is true"

근거는 만입니다 falsenil거짓이어야한다. 많은 루비 초보자에게는 문제가 있습니다. 그러나 어떤 경우에는 0이 다른 숫자처럼 취급되는 것이 좋습니다.

irb(main):002:0> (pos = 'axe' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "Found x at position 1"
irb(main):003:0> (pos = 'xyz' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "Found x at position 0"
irb(main):004:0> (pos = 'abc' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "x not found"

그러나 이러한 시스템은 부울을 숫자와 분리 된 유형으로 구별 할 수있는 언어에서만 작동합니다. 컴퓨팅 초기에는 어셈블리 언어 또는 기계 언어로 작업하는 프로그래머에게는 그러한 사치가 없었습니다. 0을 "공백"상태로 취급하고 코드에서 무언가가 발생했음을 감지하면 비트를 1로 플래그로 설정하는 것이 당연합니다. 또한이 규칙에 따라 0은 false로 처리되고 0이 아닌 값은 true로 처리됩니다. 그러나 그런 식일 필요는 없습니다.

Java : 숫자를 전혀 부울로 취급 할 수 없습니다

자바에서, true그리고 false유일한 부울 값입니다. 숫자는 부울이 아니며 부울로 캐스트 할 수도 없습니다 ( Java Language Specification, Sec 4.2.2 ).

정수형과 형 사이에는 캐스트가 없습니다 boolean.

이 규칙은 질문을 완전히 피합니다. 모든 부울 표현식은 코드에 명시 적으로 작성되어야합니다.


1
Rebol과 Red는 모두 0 값 정수를 처리합니다! 값을 true로 설정하고 별도의 NONE을 갖습니다! LOGIC에 추가하여 조건부 거짓으로 취급되는 유형 (하나의 값만있는 NONE)! 그릇된. 0을 false로 취급하는 JavaScript 코드를 작성하려고 할 때 상당한 좌절감을 발견했습니다. 동적으로 유형이 지정된 언어에 대한 엄청나게 결정적인 결정입니다. null 또는 0 일 수있는 것을 테스트하려면 쓸 if (thing === 0)필요가 없습니다. 멋지지 않습니다.
HostileFork

@HostileFork 몰라요. 나는 그것이 의미하게 찾을 0것입니다 true동적 언어 (다른 모든 정수를). 파이썬에서 잡으려고 할 0때 때때로 잡는 일이 None있었고 때로는 발견하기가 어려울 수 있습니다.
Morwenn

2
루비는 특이 치가 아닙니다. 루비는 이것을 Lisp에서 가져옵니다 (Ruby는 비밀리에 "MatzLisp"라고도 함). Lisp는 컴퓨터 과학의 주류 언어입니다. POSIX 셸에서 0은 텍스트의 일부이기 때문에 실제 값일뿐 if [ 0 ] ; then echo this executes ; fi입니다. 거짓 데이터 값은 빈 문자열이며 테스트 가능한 거짓은 명령의 실패한 종료 상태이며 0이 아닌 값으로 표시됩니다 .
Kaz

8

일반적인 경우를 다루기 전에 카운터 예제를 논의 할 수 있습니다.

문자열 비교

실제로 많은 종류의 비교에서도 마찬가지입니다. 이러한 비교 는 두 물체 사이 의 거리 를 계산 합니다. 물체가 같으면 거리가 최소화됩니다. 따라서 "비교가 성공"할 때 값은 0입니다. 그러나 실제로,의 반환 값은 부울 strcmp아니며 , 거리이며, 거리가 멀고 프로그래머가 모르는 것을 잡는 것 if (strcmp(...)) do_when_equal() else do_when_not_equal()입니다.

C ++에서는 0을 반환하면 true를 반환 하도록 재정의 strcmp하는 Distance객체를 다시 디자인 할 수 있습니다 operator bool()(그러나 다른 문제 세트에 물린 경우). 또는 일반 C에는 streq문자열이 같을 때 1을 반환하고 그렇지 않으면 0을 반환 하는 함수가 있습니다.

API 호출 / 프로그램 종료 코드

여기서 오류에 대한 결정을 내리기 때문에 문제가 발생한 이유에 대해 걱정합니다. 일이 성공하면, 당신은 특별히 알고 싶지 않습니다-당신의 의도가 실현됩니다. 따라서 반환 값은이 정보를 전달해야합니다. 부울 이 아니며 오류 코드입니다. 특수 오류 값 0은 "오류 없음"을 의미합니다. 나머지 범위는 처리해야 할 로컬 의미있는 오류 (1을 포함하여 "지정되지 않은 오류"를 의미 함)를 나타냅니다.

일반적인 경우

이 질문에 우리를 잎 : 왜 부울 값입니다 TrueFalse일반적으로 각각 1과 0으로 표현?

글쎄요, 주관적인 "이것이 더 나아졌다"는 주장 외에, 제가 생각할 수있는 몇 가지 이유 (주관적)가 있습니다 :

  • 전기 회로 유추. 전류는 1 초 동안 켜지고 0 초 동안 꺼집니다. 나는 다른 믹스보다는 (1, Yes, True, On)과 (0, No, False, Off)를 함께 사용하는 것을 좋아합니다.

  • 메모리 초기화. 내가 memset(0)많은 변수 (int, float, bools) 일 때 그들의 가치가 가장 보수적 인 가정과 일치하기를 원합니다. 예를 들어 내 합계는 초기에 0이고 술어는 거짓입니다.

어쩌면 이러한 모든 이유는 내 교육과 관련이있을 수 있습니다. 처음부터 0을 True와 연관 시키도록 교육 받았다면 다른 방향으로 갈 것입니다.


2
실제로 0을 true로 취급하는 프로그래밍 언어가 하나 이상 있습니다. 유닉스 쉘.
Jan Hudec

실제 문제 해결을위한 +1 : Morwenn의 대부분의 질문은 전혀 관련이 없습니다 bool.
dan04

@ dan04입니다. 전체 게시물의 캐스트의 선택 뒤에있는 근거에 관한 것입니다 intbool많은 프로그래밍 언어입니다. 비교 및 오류 처리는 현재 수행 된 것과 다른 방식으로 캐스팅하는 것이 적합한 장소의 예일뿐입니다.
Morwenn

6

높은 수준의 관점에서 보면 세 가지 다른 데이터 유형에 대해 이야기하고 있습니다.

  1. 참이나 거짓. 부울 대수 의 수학 규칙은 0에 false1 을 사용 하고 1에 1 을 사용 true하므로 해당 규칙을 따르는 것이 좋습니다. 이 방법은 직관적으로 더 의미가 있다고 생각합니다.

  2. 비교 결과. 여기에는 세 개의 값이 있습니다 : <, =>(아무도 없음 true) 그들에게는 각각 -1, 0 및 1의 값을 사용하는 것이 좋습니다 (또는 더 일반적으로 음수, 0 및 양수 값).

    평등을 확인하고 일반적인 비교를 수행하는 함수 만있는 경우와 같은 것을 사용하여 명시 적으로 만들어야한다고 생각합니다 strcmp(str1, str2) == 0. !부울이 아닌 값을 부울처럼 취급하기 때문에이 상황에서 사용 하는 것이 혼란 스럽습니다.

    또한 비교와 평등이 똑같을 필요는 없습니다. 예를 들어, 생년월일로 사람들을 주문하면을 Compare(me, myTwin)반환 해야 0하지만 Equals(me, myTwin)을 반환해야합니다 false.

  3. 함수의 성공 또는 실패 (해당 성공 또는 실패에 대한 세부 사항 포함) Windows에 대해 이야기하는 경우이 유형이 호출 HRESULT되며 0이 아닌 값이 반드시 실패를 나타내는 것은 아닙니다. 실제로 음수 값은 실패와 음이 아닌 성공을 나타냅니다. 성공 값은 매우 자주 발생 S_OK = 0하지만 예를 들어 S_FALSE = 1또는 다른 값일 수도 있습니다 .

C와 일부 다른 언어에서는 논리적으로 매우 다른 세 가지 데이터 유형이 실제로 단일 데이터 유형 (정수)으로 표시되고 조건에서 정수를 사용할 수 있다는 사실에 혼란이 생깁니다. 그러나 부울이 아닌 유형을 더 간단한 조건에서 사용하기 위해 부울을 재정의하는 것이 의미가 있다고 생각하지 않습니다.

또한 C의 조건에서 자주 사용되는 다른 유형 인 포인터를 고려하십시오. 거기에, 그것은 치료하는 자연이다 NULL(이로 표현 -pointer을 0로) false. 따라서 귀하의 제안을 따르면 포인터로 작업하는 것이 더 어려워집니다. (개인적으로는 포인터 NULL를 부울로 취급하는 대신 포인터를 명시 적으로 비교하는 것을 선호 합니다.)


4

대부분의 CPU에는 분기에 사용할 수있는 ZERO 플래그가 있으므로 0은 거짓 일 수 있습니다. 비교 작업을 저장합니다.

이유를 보자.

청중이 아마도 어셈블리를 읽지 않기 때문에 일부 의사 코드

c- 소스 간단한 루프 호출 10 회 흔들림

for (int foo =10; foo>0; foo-- ) /* down count loop is shorter */
{  
   wibble();
}

그것에 대한 일부 척 조립

0x1000 ld a 0x0a      'foo=10
0x1002 call 0x1234    'call wibble()
0x1005 dec a          'foo--
0x1006 jrnz -0x06      'jump back to 0x1000 if not zero
0x1008  

c- 또 다른 간단한 루프 호출이 10 번 흔들림

for (int foo =0; foo<10; foo-- ) /* up count loop is longer  */
{  
   wibble();
}

이 사건에 대한 일부 척 어셈블리

0x1000 ld a 0x00      'foo=0
0x1002 call 0x1234    'call wibble()
0x1005 dec a          'foo--
0x1006 cmp 0x0a       'compare foo to 10 ( like a subtract but we throw the result away)
0x1008 jrns -0x08      'jump back to 0x1000 if compare was negative
0x100a  

좀 더 C 소스

int foo=10;
if ( foo ) wibble()

그리고 어셈블리

0x1000 ld a 0x10
0x1002 jz 0x3
0x1004 call 0x1234
0x1007  

얼마나 짧은 지 알아?

좀 더 C 소스

int foo=10;
if ( foo==0 ) wibble()

그리고 어셈블리 (비교없이 == 0을 대체 할 수있는 한계 스마트 컴파일러를 가정하자)

0x1000 ld a 0x10
0x1002 jz 0x3
0x1004 call 0x1234
0x1007  

이제 true = 1의 규칙을 사용해 봅시다.

더 많은 c 소스 #define TRUE 1 int foo = TRUE; if (foo == TRUE) wibble ()

그리고 어셈블리

0x1000 ld a 0x1
0x1002 cmp a 0x01
0x1004 jz 0x3
0x1006 call 0x1234
0x1009 

0이 아닌 true의 경우가 얼마나 짧은 지보십시오.

실제로 초기 CPU에는 Accumulator에 작은 플래그 세트가 부착되어있었습니다.

a> b 또는 a = b인지 확인하려면 일반적으로 비교 명령이 필요합니다.

  • B가 ZERO 인 경우가 아니면 ZERO 플래그가 간단한 논리 NOR 또는 Accumulator의 모든 비트로 구현됩니다.
  • 또는 2의 보수 산술을 사용하는 경우 "부호 비트"즉 누산기의 최상위 비트 만 사용하는 음수. (대부분 우리는)

이것을 다시 말해 보자. 일부 구형 CPU에서는 ZERO와 같은 누산기 또는 0보다 작은 누산기에 대해 비교 명령을 사용할 필요가 없었습니다.

이제 왜 0이 거짓 일 수 있는지 알 수 있습니까?

이 코드는 의사 코드이며 실제 명령어 세트는 이처럼 보이지 않습니다. 어셈블리를 알고 있다면 여기에서 많은 것을 단순화하고 있습니다. 컴파일러 디자인에 대해 알고 있다면이 답변을 읽을 필요가 없습니다. 루프 언 롤링이나 브랜치 예측에 대해 아는 사람은 203 호실의 고급 강의실입니다.


2
요점을 잘하기 때문에 한 가지 여기를 만들어되지 if (foo)if (foo != 0)같은 코드를 생성해야하고, 둘째, 당신은 당신이 실제로 사용하고있는 어셈블리 언어가 명시 적 부울 피연산자 그들을 위해 테스트를 가지고 있음을 보여주는 것입니다. 예를 들어 jz의미 jump if zero합니다. 다시 말해 if (a == 0) goto target;. 그리고 수량은 직접 테스트조차되지 않습니다. 조건은 특수 기계어에 저장된 부울 플래그로 변환됩니다. 실제로 더 비슷합니다cpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
Kaz

아니 Kaz, 이전 CPU는 그렇게 작동하지 않았습니다. jz / jnz는 비교 명령을 수행하지 않고 수행 할 수 있습니다. 내 전체 게시물의 요점이었습니다.
팀 윌리스 크로프트

2
비교 명령에 대해서는 아무것도 쓰지 않았습니다.
Kaz

jz명령이 있지만없는 프로세서를 인용 할 수 있습니까 jnz? (또는 다른 비대칭 조건부 명령어 세트)
Toby Speight

3

1과 true 사이의 대응이 수학적 속성에 의해 필요하다는 것을 암시하는 많은 답변이 있습니다. 나는 그러한 재산을 찾을 수 없으며 순수한 역사적 관습이라고 제안합니다.

두 가지 요소를 가진 필드가 주어지면 덧셈과 곱셈의 두 가지 연산이 있습니다. 이 필드에서 부울 연산을 두 가지 방법으로 매핑 할 수 있습니다.

전통적으로 우리는 True를 1로, False를 0으로 식별합니다. AND는 *로, XOR은 +로 식별합니다. 따라서 OR은 포화 첨가입니다.

그러나 0으로 True를, False를 1로 쉽게 식별 할 수 있습니다. 그런 다음 *로 OR을 식별하고 +로 XNOR을 식별합니다. 따라서 AND는 포화 상태입니다.


4
Wikipedia의 링크를 따른다면 부울 대수의 개념이 두 요소로 구성된 Galois 필드의 개념과 관련되어 있다는 것을 알 수 있습니다 ( en.wikipedia.org/wiki/GF%282%29 ). 실수 0은 또한 숫자가 0과 1 인 필드이기 때문에 기호 0과 1은 일반적으로 덧셈과 곱셈을 나타내는 데 사용됩니다.
Giorgio

1
@NeilG 저는 Giorgio가 단순한 컨벤션 그 이상이라고 말하려고합니다. 부울 대수의 0과 1은 기본적으로 GF (2)의 0과 1과 동일하며, 덧셈과 곱셈과 관련하여 실수에서 0과 1과 거의 동일하게 동작합니다.
svick

1
@svick : 아니요, 곱하기 및 포화 더하기의 이름을 OR 및 AND로 바꾼 다음 레이블을 뒤집어 0이 True이고 1이 False가 될 수 있기 때문입니다. 조르지오 (Giorgio)는 이것이 부울 논리의 규칙이며 컴퓨터 과학의 규칙으로 채택되었다고 말합니다.
Neil G

1
@Neil G : 아니요, 필드에 더하기에 대한 곱셈의 분포가 필요하기 때문에 +와 * 및 0과 1을 뒤집을 수 없습니다 ( en.wikipedia.org/wiki/Field_%28mathematics%29 참조 ). + : = AND를 설정하면 그리고 * : = XOR, T XOR (T AND F) = T XOR F = T, 반면 (T XOR T) AND (T XOR F) = F AND T = F를 얻습니다. 더 이상 필드가 없습니다. 따라서 적절한 분야의 정체성으로 0과 1을 정의하는 IMO는 거짓과 진실을 매우 충실하게 포착하는 것 같습니다.
조르지오

1
@ giorgio : 나는 무슨 일이 일어나고 있는지 분명히하기 위해 답을 편집했습니다.
Neil G

3

이상하게도 0은 항상 거짓이 아닙니다.

특히, Unix 및 Posix 규칙은 EXIT_SUCCESS0 (및 EXIT_FAILURE1)으로 정의하는 것 입니다. 실제로 그것은 심지어 표준 C 규칙입니다 !

따라서 Posix 쉘 및 exit (2) syscall의 경우 0은 "성공"을 의미하며 이는 직관적 인 것보다 거짓입니다.

특히, 쉘 은 "then"분기를 따르기 위해 if프로세스 리턴 EXIT_SUCCESS(0)을 원합니다 !

Scheme에서는 (그러나 Common Lisp 또는 MELT에서는 아님) 0과 nil (즉 ()Scheme에서는)은 유일한 false 값이므로#f

동의합니다, 나는 nitpicking입니다!


3

C는 하드웨어와 가까운 저수준 프로그래밍에 사용되며, 동일한 데이터에서 비트 단위와 논리 연산 사이를 전환해야하는 영역입니다. 테스트를 수행하기 위해 숫자 표현식을 부울로 변환해야하는 경우 코드가 복잡해집니다.

다음과 같이 쓸 수 있습니다.

if (modemctrl & MCTRL_CD) {
   /* carrier detect is on */
}

오히려

if ((modemctrl & MCTRL_CD) != 0) {
    /* carrier detect is on */
}

하나의 고립 된 예에서 그렇게 나쁘지는 않지만 그렇게 해야하는 것은 성가 시게됩니다.

마찬가지로 대화 작업. 비교와 같이 부울 연산의 결과가 0 또는 1을 생성하는 데 유용 modemctrl합니다. 반송파가 비트를 감지 하는지 여부에 따라 일부 단어의 세 번째 비트를 설정한다고 가정합니다 .

flags |= ((modemctrl & MCTRL_CD) != 0) << 2;

여기서 우리는이 있어야 != 0의 biwise의 결과 감소 &로 표현 0하거나 1더 부울 정수로 변환하는 몇 가지 성가신 캐스트를 추가 할 필요가 결과는 단지 정수이기 때문에,하지만, 우리가 절약된다.

현대의 C는 이제 bool유형이 있지만 좋은 점이기 때문에 코드의 유효성을 유지하고 그렇지 않으면 발생할 수있는 이전 버전과의 호환성으로 인해 큰 손상이 발생합니다.

C가 매끈한 또 다른 예 : 4 가지 스위치로 두 개의 부울 조건 테스트 :

switch (foo << 1 | bar) {  /* foo and bar booleans are 0 or 1 */
case 0: /* !foo && !bar */
   break;
case 1: /* !foo && bar */
   break;
case 2: /* foo && !bar */
   break;
case 3: /* foo && bar */
   break;
}

싸움없이 C 프로그래머로부터 이것을 빼앗을 수 없었습니다!

마지막으로 C는 때때로 일종의 고급 어셈블리 언어 역할을합니다. 어셈블리 언어에는 부울 유형이 없습니다. 부울 값은 메모리 위치 또는 레지스터에서 비트 또는 0 대 0이 아닌 값입니다. 정수 0, 부울 0 및 주소 0은 모두 어셈블리 언어 명령어 세트 (및 아마도 부동 소수점 0)에서 동일한 방식으로 테스트됩니다. C와 다른 언어를 컴파일하기위한 대상 언어로 C를 사용하는 경우와 같이 C와 어셈블리 언어의 유사성은 유용합니다.


0

부울 또는 진리 값에는 2 개의 값만 있습니다. 진실과 거짓.

이러한한다 없는 정수로 표현되지만 비트 (0과 1) 등.

0 또는 1 이외의 다른 정수가 거짓이 아니라고 말하는 것은 혼란스러운 진술입니다. 진리표는 정수가 아니라 진리 값을 처리합니다.

예상 값에서 -1 또는 2는 모든 진리표와 그와 관련된 부울 논리를 모두 위반합니다.

  • 0 AND -1 ==?!
  • 0 또는 2 ==?!

대부분의 언어에는 일반적 boolean으로 정수와 같은 숫자 유형으로 캐스트 할 때 정수 값 0으로 캐스트되는 false 가 표시되는 유형이 있습니다.


1
0 AND -1 == 부울 값을 캐스트하십시오. 그것이 내 질문에 대한 이유이며 왜 TRUE또는로 캐스팅합니까 FALSE? 나는 결코 말하지 않았다. 어쩌면 내가 의도 한 것은 아니었다. 정수는 참이거나 거짓이었다. 나는 그들이 불리언으로 캐스트 될 때 그것들이 왜 평가되는지에 대해 물었다.
Morwenn

-6

궁극적으로 일부 API는 엉터리이기 때문에 핵심 언어를 깨는 것에 대해 이야기하고 있습니다. Crappy API는 새로운 것이 아니며 언어를 깨뜨려 서 고칠 수는 없습니다. 0이 거짓이고 1이 참이라는 수학적 사실이며, 이것을 존중하지 않는 언어는 근본적으로 깨졌습니다. 3 방향 비교는 틈새이며 bool가능한 3 가지 결과를 반환하므로 결과가 암시 적으로 변환되는 비즈니스는 없습니다 . 이전 C API는 단순히 끔찍한 오류 처리 기능을 가지고 있으며 C에는 끔찍한 인터페이스를 갖지 않는 데 필요한 언어 기능이 없기 때문에 어려움을 겪고 있습니다.

암시 적 정수-> 부울 변환이없는 언어의 경우는 아닙니다.


11
"0이 거짓이고 1이 참이라는 수학적 사실"Erm.
R. Martinho Fernandes

11
"0이 거짓이고 1이 참이라는 수학적 사실"에 대한 참조를 인용 할 수 있습니까? 당신의 대답은 위험한 소리처럼 들립니다.
Dan Pichelman

14
수학적 사실은 아니지만 19 세기 이래 수학적 관습이었습니다.
찰스 E. 그랜트

1
부울 대수는 유한 필드로 표현되며 0과 1은 덧셈 및 곱셈과 유사한 연산의 항등 요소입니다. 이러한 작업은 각각 OR과 AND입니다. 실제로, 부울 대수는 병렬이 AND를 +나타내고 기호가 OR을 나타내는 일반 대수와 매우 유사 합니다. 예를 들어 abc + a'b'c의미 (a and b and c) or (a and (not b) and (not c))합니다.
Kaz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.