[c] C에 부호없는 수레가없는 이유는 무엇입니까?

나는 그 질문이 이상해 보인다. 프로그래머는 때때로 너무 많이 생각합니다. 읽어주세요 …

CI의 사용 signedunsigned정수 많이. 부호없는 정수를 부호없는 변수에 할당하는 것과 같은 일을하면 컴파일러가 경고한다는 사실이 마음에 듭니다. 부호없는 정수와 훨씬 더 많은 부호를 비교하면 경고가 표시됩니다.

나는이 경고를 좋아한다. 그들은 내 코드를 올바르게 유지하도록 도와줍니다.

우리는 왜 수레에 대해 같은 사치를 가지고 있지 않습니까? 제곱근은 절대 음수를 반환하지 않습니다. 음의 float 값이 의미가없는 다른 곳도 있습니다. 부호없는 플로트에 대한 완벽한 후보.

Btw-수레에서 부호 비트를 제거하여 얻을 수있는 단일 정밀도의 비트에 대해서는 열의가 아닙니다. 나는 float그들이 지금처럼 s에 매우 만족 합니다. 때로는 부동 소수점을 부호없는 것으로 표시하고 정수와 동일한 종류의 경고를 얻고 싶습니다.

부호없는 부동 소수점 숫자를 지원하는 프로그래밍 언어를 알지 못합니다.

왜 존재하지 않는지 아십니까?


편집하다:

나는 x87 FPU에 부호없는 수레를 다루는 지시가 없다는 것을 알고 있습니다. 부호있는 부동 명령어를 사용하십시오. 부호있는 정수의 오버플로가 정의되지 않은 것과 같은 방식으로 오용 (예 : 0 미만으로 간주)이 정의되지 않은 동작으로 간주 될 수 있습니다.



답변

C ++에서 부호없는 부동 소수점을 지원하지 않는 이유는 CPU가 실행할 동등한 기계 코드 작업이 없기 때문입니다. 따라서 그것을 지원하는 것은 매우 비효율적입니다.

만약 C ++이 그것을 지원했다면, 때때로 부호없는 float를 사용하고 성능이 막 죽었 음을 깨닫지 못할 수 있습니다. C ++에서 지원하는 경우 모든 부동 소수점 연산이 서명되어 있는지 여부를 확인해야합니다. 그리고 수백만 개의 부동 소수점 연산을 수행하는 프로그램의 경우 이는 허용되지 않습니다.

따라서 하드웨어 구현자가 지원하지 않는 이유는 무엇입니까? 그리고 그에 대한 대답은 원래 정의되지 않은 부동 표준이 없다는 것입니다. 언어는 이전 버전과 호환되기를 원하기 때문에 언어를 추가하더라도 언어를 사용할 수 없습니다. 부동 소수점 사양을 보려면 IEEE 표준 754 부동 소수점을 살펴보십시오 .

부동 소수점 또는 이중을 캡슐화하고 음수를 전달하려고하면 경고를 던지는 부호없는 부동 소수점 클래스를 만들어서 부호없는 부동 소수점 유형을 갖지 않을 수 있습니다. 이것은 덜 효율적이지만, 당신이 그들을 강하게 사용하지 않는다면 아마 약간의 성능 손실에 신경 쓰지 않을 것입니다.

나는 부호없는 플로트를 갖는 것이 유용하다는 것을 분명히 봅니다. 그러나 C / C ++는 안전을 능가하는 모든 사람에게 가장 적합한 효율성을 선택하는 경향이 있습니다.


답변

C / C ++에서 부호있는 정수와 부호없는 정수에는 큰 차이가 있습니다.

value >> shift

부호있는 값은 최상위 비트를 변경하지 않고 그대로두고 (부호 확장), 부호없는 값은 최상위 비트를 지 웁니다.

부호없는 부동 소수점이없는 이유는 음수 값이 없으면 모든 종류의 문제에 빠르게 부딪 치기 때문입니다. 이걸 고려하세요:

float a = 2.0f, b = 10.0f, c;
c = a - b;

c는 어떤 가치가 있습니까? -8. 그러나 음수가없는 시스템에서는 이것이 무엇을 의미합니까? FLOAT_MAX-아마도 8? 실제로 FLOAT_MAX-8은 정밀 효과로 인해 FLOAT_MAX이므로 작동하지 않으므로 일이 훨씬 까다로워집니다. 좀 더 복잡한 표현의 일부인 경우 :

float a = 2.0f, b = 10.0f, c = 20.0f, d = 3.14159f, e;
e = (a - b) / d + c;

2의 보수 시스템의 특성으로 인해 정수에는 문제가되지 않습니다.

또한 표준 수학 함수를 고려하십시오. sin, cos 및 tan는 입력 값의 절반에 대해서만 작동하며 값 로그 <1을 찾을 수없고 2 차 방정식을 풀 수 없습니다. x = (-b +/- root ( bb-4.ac)) / 2.a 등. 실제로 복잡한 함수에서는 어딘가 음수 값을 사용하는 다항식 근사치로 구현되는 경향이 있으므로 복잡한 함수에서는 작동하지 않을 수 있습니다.

따라서 부호없는 수레는 쓸모가 없습니다.

그러나 그것이 범위 값을 플로트 값으로 검사하는 클래스가 유용하지 않다는 것을 의미하지는 않습니다. 예를 들어 RGB 계산과 같이 주어진 범위로 값을 고정하고 싶을 수 있습니다.


답변

(옆으로, Perl 6을 사용하면

subset Nonnegative::Float of Float where { $_ >= 0 };

Nonnegative::Float다른 유형과 마찬가지로 사용할 수 있습니다 .)

부호없는 부동 소수점 연산에 대한 하드웨어 지원은 없으므로 C는이를 지원하지 않습니다. C는 대부분 “휴대용 어셈블리”, 즉 특정 플랫폼에 묶이지 않고 금속에 가깝도록 설계되었습니다.

[편집하다]

C는 어셈블리와 같습니다. 당신이 보는 것은 정확히 당신이 얻는 것입니다. 암시적인 “이 플로트가 음수가 아닌지 확인하겠습니다”는 디자인 철학에 위배됩니다. 정말로 원한다면 추가 assert(x >= 0)하거나 유사하게 할 수 있지만 명시 적으로해야합니다.


답변

서명 된 int가 제공 할 수있는 것보다 더 큰 가치 마진이 필요하기 때문에 서명되지 않은 int가 생성되었다고 생각합니다.

플로트는 훨씬 큰 마진을 가지므로 부호없는 플로트에 대한 ‘물리적’필요는 없었습니다. 그리고 당신이 당신의 질문에 자신을 지적함에 따라, 추가 1 비트 정밀도는 죽일 것이 없습니다.

편집 : Brian R. Bondy
답변을 읽은 후 내 대답을 수정해야합니다. 기본 CPU에 서명되지 않은 부동 소수점 연산이 없었 음이 분명합니다. 그러나 나는 이것이 위에서 언급 한 이유에 따라 디자인 결정이라고 생각합니다. 😉


답변

Treb이 올바른 길을 가고 있다고 생각합니다. 부호없는 해당 유형이있는 정수의 경우 더 중요합니다. 그것들은 비트 시프 팅 에 사용되며 비트 맵에 사용 되는 것들입니다 . 부호 비트가 막 시작되었습니다. 예를 들어, 음수 값을 오른쪽으로 이동하면 결과 값은 C ++로 정의 된 구현입니다. 부호없는 정수로 오버플로하거나 오버플로를 수행하면 의미가 완벽하게 정의되어 있습니다.

따라서 정수의 경우 최소한 경고를 제공하는 것보다 별도의 부호없는 유형이 필요합니다. 수레에 대해 위의 모든 사항을 고려할 필요는 없습니다. 따라서 하드웨어 지원이 실제로 필요하지 않으며 C는 이미 그 시점에서 지원하지 않습니다.


답변

제곱근은 절대 음수를 반환하지 않습니다. 음의 float 값이 의미가없는 다른 곳도 있습니다. 부호없는 플로트에 대한 완벽한 후보.

C99는 복소수와 제네릭 형식의 sqrt를 지원하므로 sqrt( 1.0 * I)음수가됩니다.


주석 작성자 sqrt는 함수가 아닌 유형 일반 매크로를 언급하고 있다는 점에서 약간의 광택을 강조 했으며 실제 구성 요소에 대한 복합 자르기를 통해 스칼라 부동 소수점 값을 반환합니다.

#include <complex.h>
#include <tgmath.h>

int main ()
{
    complex double a = 1.0 + 1.0 * I;

    double f = sqrt(a);

    return 0;
}

또한 복소수의 sqrt의 실제 부분이 양수 또는 0이고 sqrt (1.0 * I)가 sqrt (0.5) + sqrt (0.5) * I -1.0이 아니기 때문에 brain-fart도 포함합니다.


답변

IEEE 부동 소수점 사양에만 서명하고 대부분의 프로그래밍 언어에서 사용한다는 것이 달려 있습니다.

IEEE-754 부동 소수점 숫자에 대한 Wikipedia 기사

편집 : 또한 다른 사람들이 지적했듯이 대부분의 하드웨어는 음이 아닌 부동 소수점을 지원하지 않으므로 하드웨어 지원이 있기 때문에 일반적인 종류의 부동 소수점이 더 효율적입니다.