programing

C는 왜 싸인이 없는 수레가 없는 거죠?

goodjava 2022. 11. 30. 21:16

C는 왜 싸인이 없는 수레가 없는 거죠?

알아요, 질문이 좀 이상한 것 같아요.프로그래머들은 때때로 너무 많은 생각을 한다.읽어주세요...

에서는 C를 합니다.signed ★★★★★★★★★★★★★★★★★」unsigned정수를 많이 쓰죠.부호 없는 변수에 부호 있는 정수를 할당하면 컴파일러가 경고해 주는 것이 마음에 듭니다.부호 없는 정수 등과 비교하면 경고가 표시됩니다.

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

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

그나저나 나는 수레에서 간판 조각을 제거함으로써 얻을 수 있는 여분의 정밀도에 그다지 관심이 없다.는 너무 행복해요.float현재와 같습니다.가끔 플로트에 부호 없는 마크를 붙이고 정수와 같은 경고를 받고 싶습니다.

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

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


편집:

x87 FPU에는 서명되지 않은 플로트에 대한 지침이 없다는 것을 알고 있습니다.서명된 플로트 명령을 사용합니다.오용(예: 0 미만으로 가는 것)은 부호 있는 정수의 오버플로우가 정의되지 않은 것과 같은 방식으로 정의되지 않은 동작으로 간주될 수 있다.

C++가 부호 없는 플로트를 지원하지 않는 이유는 CPU가 실행할 수 있는 동등한 머신 코드 조작이 없기 때문입니다.따라서 이를 지원하는 것은 매우 비효율적입니다.

C++가 지원하는 경우 서명되지 않은 플로트를 사용하여 퍼포먼스가 중단되었음을 인식하지 못할 수 있습니다.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 (b.b - 4.a) / 2.a 등을 풀 수 없습니다.사실, 이러한 함수는 음의 값을 사용하는 다항식 근사치로 구현되는 경향이 있기 때문에 어떤 복잡한 함수에도 작동하지 않을 수 있습니다.

그래서, 싸인이 없는 수레는 꽤 쓸모가 없다.

단, 플로트 값을 체크하는 클래스가 유용하지 않다는 것은 아닙니다.예를 들어 RGB 계산과 같이 값을 특정 범위로 클램프할 수 있습니다.

C의 부호 없는 정수형은 추상 대수환의 규칙에 따르도록 정의된다.예를 들어, 모든 값 X와 Y에 대해 Y에 X-Y를 더하면 X가 생성됩니다.부호 없는 정수형은 다른 수치형(또는 크기가 다른 부호 없는 유형)과의 변환을 수반하지 않는 모든 경우에 이러한 규칙을 준수할 것을 보증하며 이러한 유형의 가장 중요한 기능 중 하나입니다.경우에 따라서는 부호 없는 유형만이 제공할 수 있는 추가 보증을 대가로 음수를 나타내는 기능을 포기하는 것이 좋습니다.부동소수점 타입은 부호여부에 관계없이 대수 링의 모든 규칙을 준수할 수 없습니다(예를 들어 X+Y-Y가 X와 동일하다는 것을 보증할 수 없습니다).또한 IEEE는 (특정 값이 자신들과 동등하지 않은 것을 요구함으로써) 동등 클래스의 규칙조차 준수할 수 없습니다."서명되지 않은" 부동소수점 유형은 일반 부동소수점 유형으로는 허용되지 않는 공리를 수용할 수 없다고 생각하기 때문에 어떤 이점을 제공할 수 있을지 모르겠습니다.

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

플로트는 마진이 훨씬 크기 때문에 부호 없는 플로트에 대한 '물리적' 필요성이 전혀 없었습니다.그리고 당신이 질문에서 지적했듯이, 추가 1비트의 정밀도는 치명적이지 않습니다.

편집: Brian R의 답변을 읽은 후. 본디, 내 대답을 수정해야겠어기본 CPU에 서명되지 않은 부동 연산이 없었다는 그의 말이 맞습니다.다만, 상기의 이유에 근거한 설계 결정이라고 생각하고 있습니다.-)

부호 없는 부동 소수점 숫자를 지원하는 프로그래밍 언어는 모릅니다.왜 그들이 존재하지 않는지 아십니까?

부호가 없는 플로트가 존재합니다.「 」를 .unsigned float16GPU 하드웨어의 경우 (11개의 분수 비트, 5개의 지수 비트, 0개의 부호 비트), HDR 포맷 DXGI_FORMAT_BC6H.대부분의 컴퓨팅 하드웨어에서 매우 드물기 때문에 메인스트림 프로그래밍 언어에서는 생략할 수 있습니다.이 사용법에서는 검은 색보다 어두운 색상은 의미가 없기 때문에 기호는 생략됩니다.

훨씬 일반적인 IEEE의 절반 또는 서명도 가능float16_tHDR 이미지 및 저대역폭 텐서용 그래픽스 및 머신러닝 분야에서 많이 사용되고 있지만 C/C++에 통합되는 영광을 누리지 못하고 있습니다(단, CUDA/HLSL과 같은 보다 도메인 고유의 언어에는 없습니다).half/float16_t또, C++의 제안도 있습니다.그래서 만약signed float16컴파일러 고유의 확장자(gcc__fp16 등) 이외의 C++로 만들 수 없습니다.unsigned float16에는 :b 가 거의 없습니다.또, CUDA 나 HLSL 도, 언어에 부호 없는 타입을 가지는 것은 아니고, 텍스처 정의 자체(를 참조)에 기재되어 있습니다.DDS 파일 또는 GPU 텍스처 메모리).그때까지 도우미 라이브러리를 통한 컴파일러 지원 없이 보다 이국적인 유형을 계속 구현해야 합니다.

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

합니다.따라서 C99는 sqrt를 합니다.sqrt( 1.0 * I)이이됩됩됩됩됩


은 위에서 약간 했는데, 그는 제가 '', '유형일반', '유형일반', '유형일반', '유형일반론자들은 ' 일반론', '활자 일반론'을 .sqrt컴포넌트( 「Complex」, 「Complex」)로.

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

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

    double f = sqrt(a);

    return 0;
}

또한 복소수 제곱의 실제 부분이 양수 또는 0이고 제곱트(1.0)가 있기 때문에 브레인파트를 포함한다.*I)는 sqrt(0.5) + sqrt(0.5)* -1.0이 아닙니다.

나는 트렙이 올바른 길을 가고 있다고 생각한다.정수의 경우 부호 없는 해당 유형을 갖는 것이 더 중요합니다.비트 시프트에 사용되는 과 비트 맵에 사용되는 것이 있습니다.신호 비트가 방해가 됩니다.예를 들어 음의 값을 오른쪽 이동하면 C++에서 정의된 구현 값이 됩니다.부호 없는 정수를 사용하거나 오버플로우하는 것은 방해되는 비트가 없기 때문에 완벽하게 정의된 의미를 가집니다.

따라서 적어도 정수의 경우 경고만 하는 것보다 별도의 부호 없는 유형이 더 중요합니다.플로트에 대해서는 위의 모든 사항을 고려할 필요가 없습니다.따라서 하드웨어 지원은 실제로 필요하지 않으며, C는 이 시점에서는 이미 지원하지 않습니다.

(여담으로 Perl 6에서는

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

""를 사용할 수 .Nonnegative::Float다른 타입과 마찬가지로)

서명되지 않은 부동소수점 연산에 대한 하드웨어 지원은 없으므로 C는 제공하지 않습니다.C는 대부분 "휴대용 조립체"로 설계되어 있습니다.즉, 특정 플랫폼에 얽매이지 않고 금속에 최대한 가까이 접근할 수 있습니다.

[편집]

다고 하다보여지는 것이 바로 그것입니다.암묵적인 "이 플로트가 부정적이지 않은지 확인하겠습니다"는 설계 이념에 어긋납니다. '아까부터' '아까부터' '아까부터'를 수 있어요.assert(x >= 0)아니면 비슷하지만 그걸 명시적으로 해야 돼요.

IHMO는 하드웨어 또는 소프트웨어에서 서명된 부동소수점 유형과 서명되지 않은 부동소수점 유형을 모두 지원하는 것이 너무 번거롭기 때문입니다.

정수 타입의 경우, 2의 보완이라는 멋진 속성을 사용하여 대부분의 상황에서 부호 있는 정수 연산과 부호 없는 정수 연산 모두동일한 논리 유닛을 사용할 수 있습니다. 왜냐하면 결과는 add, sub, non-widthing mul 및 대부분의 비트 단위 연산과 동일하기 때문입니다.서명된 버전과 서명되지 않은 버전을 구별하는 작업의 경우 대부분의 논리를 공유할 수 있습니다.예를들면

  • 산술 및 논리 시프트에서는 상위 비트의 필러를 약간만 변경하면 됩니다.
  • 확폭 곱셈은 주요 부품에 동일한 하드웨어를 사용한 후 결과를 조정하여 부호도를 변경할 수 있습니다.실제 멀티플라이어에 사용되는 것은 아니지만, 할 수 있습니다.
  • 부호화된 비교는 상위 비트를 전환하거나 를 추가하여 부호 없는 비교로 쉽게 변환할 수 있습니다.또한 이론적으로는 하드웨어에서는 사용되지 않을 수 있지만 한 가지 유형의 비교(8080 또는 8051)만 지원하는 시스템에서 유용합니다.

1의 보완을 사용하는 시스템도 논리를 약간만 수정하면 됩니다.이는 단순히 가장 중요하지 않은 비트로 둘러싸인 반송 비트이기 때문입니다.간판 규모 시스템은 확실하지 않지만 내부적으로 1의 보수를 사용하는 것 같아서 같은 것이 적용됩니다.

유감스럽게도 부동소수점 타입의 고급스러움은 없습니다.부호 비트를 해제하는 것만으로 서명되지 않은 버전을 얻을 수 있습니다.그럼 그 비트는 어디에 써야 할까요?

  • 범위를 지수에 추가하여 늘립니다.
  • 가수에 추가하여 정밀도를 높입니다.일반적으로 범위보다 정밀도가 더 필요하기 때문에 이것은 종종 더 유용합니다.

그러나 두 가지 선택 모두 더 넓은 가치 범위를 수용하기 위해 더 큰 추가 요소가 필요합니다.이로 인해 로직의 복잡성이 높아집니다.가산기의 상단 비트는 대부분의 시간 동안 사용되지 않고 그대로 있습니다.증배, 분할, 기타 복잡한 동작에는 더 많은 회로가 필요합니다.

소프트웨어 부동소수점을 사용하는 시스템에서는 메모리 가격이 너무 높았던 시기에는 예상하지 못했던 각 기능에 대해 2가지 버전이 필요합니다.그렇지 않으면 서명된 함수와 서명되지 않은 함수의 일부를 공유하는 "교묘한" 방법을 찾아야 합니다.

그러나 부동소수점 하드웨어는 C가 발명되기 훨씬 전에 존재했기 때문에 C에서 선택한 것은 위에서 언급한 이유로 하드웨어 지원이 부족했기 때문이라고 생각합니다.

즉, Khronos 그룹의 10비트11비트 부동소수점 타입과 같이 주로 이미지 처리를 위한 몇 가지 특별한 부호 없는 부동소수점 포맷이 존재합니다.

IEEE 부동소수점 사양만 서명되어 있고 대부분의 프로그래밍 언어가 이를 사용하는지에 따라 다를 수 있습니다.

IEEE-754 부동소수점 숫자에 관한 Wikipedia 문서

편집: 또한 다른 사람들이 지적한 바와 같이 대부분의 하드웨어는 네거티브가 아닌 플로트를 지원하지 않기 때문에 하드웨어가 지원되므로 일반 플로트를 사용하는 것이 더 효율적입니다.

내 생각에 가장 큰 이유는 서명되지 않은 플로트는 서명되지 않은 int에 비해 사용이 매우 제한적이기 때문이다.하드웨어가 지원하지 않기 때문이라는 주장은 믿지 않습니다.구형 프로세서는 부동소수점 기능이 전혀 없었고 모두 소프트웨어로 에뮬레이트되었습니다.서명되지 않은 플로트가 유용했다면 소프트웨어에 먼저 구현되고 하드웨어도 그에 따라 구현되었을 것입니다.

C 컴파일러의 타깃이 되는 프로세서는 부호 없는 부동소수점 숫자를 처리하는 좋은 방법이 없기 때문이라고 생각합니다.

좋은 질문입니다.

말씀하신 대로 컴파일 시 경고만을 위한 것으로 동작에 변화가 없는 경우 기본 하드웨어는 영향을 받지 않으므로 C++/Compiler 변경에 불과합니다.

저도 이전에 같은 방법으로 당첨된 적이 있습니다만, 문제는 다음과 같습니다.별로 도움이 되지 않을 것이다.컴파일러는 기껏해야 정적 할당을 찾을 수 있습니다.

unsigned float uf { 0 };
uf = -1f;

또는 최소한으로 길게

unsigned float uf { 0 };
float f { 2 };
uf -= f;

하지만 그게 다예요.부호 없는 정수형에서는 정의된 랩어라운드(모듈러 연산과 같은 동작)도 얻을 수 있습니다.

unsigned char uc { 0 };
uc -= 1;

이 'uc' 뒤에 있는 값은 255입니다.

부호 없는 플로트 타입이 주어진 경우 컴파일러는 같은 시나리오에서 무엇을 할 수 있을까요?컴파일 시 값을 알 수 없는 경우 먼저 계산을 실행하고 부호 검사를 수행하는 코드를 생성해야 합니다.그러나 이러한 계산의 결과가 부호 없이 선언된 부동에 저장해야 하는 값인 "-5.5"가 될 경우 어떻게 됩니까?적분형처럼 모듈식 연산을 시도할 수 있지만, 여기에는 다음과 같은 문제가 있습니다.가장 큰 값은 의심할 여지 없이 무한대입니다. 작동하지 않으므로 "infinity - 1"을 사용할 수 없습니다.그것이 가질 수 있는 가장 큰 뚜렷한 가치를 추구하는 것 또한 당신이 그것에 대한 위험에 직면하기 때문에 실제로 효과가 없을 것이다.'NaN'이 후보가 될 것 같아요.번호가 원래 포함되어 있던 모든 정보를 잃게 됩니다.이러한 정보는, 특별히 확인할 필요가 있기 때문에, 도움이 되지 않습니다.따라서, 자신의 번호가 긍정인지 아닌지를 확인하는 것이 좋습니다.

마지막으로 모듈로가 잘 정의되어 있기 때문에 고정점수에는 문제가 없습니다.

언급URL : https://stackoverflow.com/questions/512022/why-doesnt-c-have-unsigned-floats