정수가 데이터 유형으로 너무 많이 사용됩니까?


9

대부분의 응용 프로그램 개발자는 실제로 부호없는 정수를 사용하는 장소에서 부호있는 정수를 사용합니까? 나는 항상 그것을하고, 동료들도 그렇게한다. 필자는 델파이 VCL 이외의 다른 광범위한 코드베이스를 많이 보지 못했으며 인터넷의 예제는 일반적으로 정수를 사용합니다. VCL 개발자는 자체 데이터 유형을 사용하지만 (변수 선언에 가장 지연되지 않는 방법 임).

이와 같은 코드에 대해서는 약간 두려운 것 같습니다.

TStuffRec = record
   recordID : Integer;
   thingID : Integer;
   otherThingID : Integer;
end;

다음과 같이 쓸 수있을 때

TStuffRec = record
   recordID : Cardinal;
   thingID : Cardinal;
   otherThingID : Cardinal;
end;

기능적으로 이러한 레코드는 거의 항상 동일하게 작동하며 64 비트 Delphi에서도 계속 동일하게 작동합니다. 그러나 매우 큰 숫자는 변환 문제가 있습니다.

그러나 부호없는 정수를 사용하는 데에도 단점이 있습니다. 주로 두 가지를 혼합하는 것이 얼마나 성가 신지에 기인합니다.

실제 질문은 실제로 이것이 모범 사례에 포함되거나 고려되는 것입니까? 보통 개발자에게 달려 있습니까?


5
피터, 델파이 전용 답변 만 찾고 있습니까?
Adam Lear

3
@Anna Delphi 데이터 유형의 작동 방식을 이해하면 가장 훌륭한 답변을 얻을 수 있습니다. C 프로그래머 가이 질문을 이해하고 대답 할 수 있다고 확신합니다.
피터 터너

답변:


9

델파이에서 부호없는 정수 유형을 많이 사용하지 않는 한 가지 이유는 부호있는 정수와 혼합 될 때 문제를 일으킬 수 있기 때문입니다. 한 번 나를 물린 사람이 있습니다.

for i := 0 to List.Count - 1 do
  //do something here

나는 i부호없는 정수로 선언했다. (결국 0에서 시작하는 목록의 인덱스이며, 음수 List.Count일 필요는 없다.) 0 일 때 루프가 예상대로 단락되지는 않는다. 0 - 1매우 높은 양수로 평가됩니다. 죄송합니다!

서명 된 혼합에 내재 된 잠재적 인 안전 문제와 부호없는 정수 및 범위 문제 사이에, (당신은보다 큰 양수를 필요로하는 거라면 high(signed whatever)꽤 가능성이 당신이 또한보다 큰 양수 필요로 오게이다, high(unsigned whatever)그래서 이동도를 동일한 크기의 부호있는 부호에서 부호없는 부호로 전환하는 대신 다음 큰 크기까지는 일반적으로 올바른 조치입니다.) 대부분의 데이터를 나타낼 때 부호없는 정수에 너무 많은 용도를 찾지 못했습니다.


2
다소 관련, 잠재적으로의 데이터 유형 사용의 주요 위험 중 하나 작은 (단지 부호 대 서명 반대) 필요 이상으로는 종료 조건은 당신이 계획보다 큰 경우, 당신은 실제로 무한 루프로 끝날 수 있다는 것입니다 카운터가 계속해서 오버플로됩니다. 그것은 어리석은 소리로 들리지만 한 번은 가능한 모든 바이트 값을 반복 해야하는 프로그램을 작성했으며 마침내 바이트 카운터로 할 수 없다는 것을 확신하기까지 약 15 분이 걸렸습니다.
Aaronaught

@Aaronaught : 델파이에는 없습니다. (내장 오버플로 검사를 비활성화하는 것과 같은 어리석은 짓을하지 않는 한) 적어도 루프가 아닌 카운터 오버플로가 발생하면 예외가 발생합니다. 여전히 버그이지만 추적하기가 훨씬 쉽습니다.
메이슨 휠러

당신이 그렇게 말한다면. 델파이에서는 항상 오버플로 검사를 비활성화했습니다. 해시 코드 및 체크섬과 같은 것들로부터 오탐 (false positive)으로 끝없이 충격을받은 후, 나는 그 "기능"을 완전히 포기했습니다. 그러나 나는 당신이 옳다고 생각합니다. 그것은 그 특정 오류를 잡았을 것입니다.
Aaronaught

@Aaronaught : 글쎄, 당신은 오버플로 및 랩을 위해 특별히 설계된 해시 코드 및 체크섬과 같은 것들에 대해 비활성화하고 싶을 것입니다. 그러나 오버플로 및 랩으로 설계 되지 않은 범용 계산 의 경우 중요한 안전 기능이며 끄는 것은 안전 벨트가없는 운전과 비슷합니다.
메이슨 휠러

어쩌면 잊어 버렸지 만 오버플로 검사 및 컴파일러 지시문은 이전 버전의 Delphi에서는 매우 버그가있었습니다. 디버거가 {$ O-} / {$ O +} 블록의 중간에 직접 정지하여 오버플로를 즐겁게보고 난 후 여러 차례에 걸쳐 머리카락이 찢어지는 것을 생생하게 기억할 수 있습니다. 잠시 후 나는 더 이상 참을 수 없었고 그것을 전 세계적으로 막을 수 없었습니다. 다시, 예, 그것은이 문제를 잡았을 것입니다. 그러나 나는 여전히 그것이 오탐의 가치가 있다고 생각하지 않습니다. 물론 각자 자신에게!
Aaronaught

3

솔직히 나는 습관적으로 정수를 사용하는 경향이 있습니다. 나는 그들이 대부분의 상황에 충분히 큰 범위를 제공하고 음수 값 (예 : -1)을 허용한다는 사실에 익숙해졌습니다. 실제로 bytes / word / shortint를 사용하는 것이 더 적합 할 것입니다. 이제 그것에 대해 생각하면 다음과 같은 지점에 집중할 수 있습니다.

  • 원근법. Tilemap 크기는 192x192 타일로 제한되므로 타일 및 루프 주소 지정에 바이트를 사용할 수 있습니다. 그러나지도 크기를 늘리려면 모든 사용 과정을 거쳐 단어와 같이 바꿔야합니다. 오프 맵 오브젝트를 허용해야 할 때 smallint로 변경하려면 다시 가야합니다.

  • 루프. "i : = 0에서 Count-1"로 루프를 작성하는 경우가 종종 있습니다. "i"가 바이트이고 Count = 0이면 루프가 0에서 255까지 실행되는 경우 어떻게됩니까?

  • 제복. "var i : integer;"를 기억하고 적용하는 것이 더 쉽습니다. 각각의 경우에 멈추고 "흠 .. 여기서 우리는 0..120 범위. 바이트 .. 충분하지 않습니다. 아아! " 또는 "왜이 부분이 shortint가 아닌 smallint입니까?"

  • 결합. 둘 이상의 클래스를 함께 결합해야 할 때 목적에 따라 다른 데이터 유형을 사용하고있을 수 있으며 더 넓은 유형을 사용하면 불필요한 변환을 건너 뛸 수 있습니다.

  • -1. 값이 0..n-1 범위에 있더라도 종종 "값 없음 / 알 수 없음 / 초기화되지 않은 / 값 없음"값을 설정해야합니다. 이는 일반적으로 -1입니다.

정수를 사용하면 이러한 모든 문제를 건너 뛰고, 필요하지 않은 저수준 최적화를 잊어 버리고, 더 높은 수준으로 가서 더 실제적인 문제에 집중할 수 있습니다.

PS 언제 다른 유형을 사용합니까?

  • 카운터는 부정적이지 않으며 클래스 외부에서 읽기 전용입니다.
  • 성능 / 메모리 이유로 특정 장소에서 더 짧은 데이터 유형을 사용해야합니다.

1

가장 좋은 방법은 사용중인 데이터 (예상 데이터)의 요구에 맞는 데이터 유형을 사용하는 것입니다.

C # 예제 : 0에서 255까지만 지원하면 바이트를 사용합니다.

1,000,000 개의 음수와 양수를 지원해야한다면 int.

4.2 억보다 크면 오래 사용하십시오.

올바른 유형을 선택하면 프로그램은 최적의 메모리 양을 사용하고 다른 유형은 다른 양의 메모리를 사용합니다.

다음은 MSDN의 C # int 참조입니다.

int 
 -2,147,483,648 to 2,147,483,647
 Signed 32-bit integer

uint 
 0 to 4,294,967,295
 Unsigned 32-bit integer

long 
 -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
 Signed 64-bit integer

ulong 
 0 to 18,446,744,073,709,551,615
 Unsigned 64-bit integer

C # (또는 일반적으로 .net)에서 128 비트 컴퓨터에서 long 및 ulong이 128 비트가됩니까? Delphi에서 Integer데이터 유형은 32 비트 시스템에서 32 비트이고 64 비트 시스템에서 64 비트 일 것입니다.
피터 터너

1
@Peter Turner : 아니요, C # 에서는 코드가 실행되는 시스템에 관계없이 int간단한 약어입니다 System.Int32.
nikie

@ Nikie, type int System.Int32그 효과 와 비슷 합니까? 향후 버전의 프레임 워크에서 쉽게 변경 될 수 있습니까?
피터 터너 (Peter Turner)

@ 피터 터너 / 니키 (sizeof (int) .ToString ()); ==> 4를 반환합니다 (sizeof (Int64) .ToString ()); ==> 64 비트 Windows OS에서 8을 반환합니다. Nikie, 통계, int는 실제로 정당하고 Int32입니다.
Jon Raynor

1
주의 할 점은이 모든 종류의 준수공용 언어 사양 . uint이러한 비 호환 유형 중 하나입니다. 이는 라이브러리가 작성된 언어 이외의 .NET 언어에서 해당 API를 사용하지 못하게하기 위해 공개적으로 노출 된 API에서 사용해서는 안됩니다. 이는 .NET 프레임 워크이기도합니다. API 자체는 사용하는 intuint할 것입니다.
Adam Lear

1

부호없는 정수 유형은 기수를 나타내는 언어로 기수를 나타내는 경우에만 사용해야합니다. C를 실행 한 컴퓨터가 작동하는 방식으로 인해 부호없는 정수 유형은 mod-2 ^ n 대수 고리의 멤버로 작동했으며, 오버플로 된 계산은 예상대로 "포장"할 수 있음을 의미합니다. 이러한 행동이 기수 또는 수학 정수의 행동과 일치하지 않을 때에도 추상 대수 고리로 행동해야합니다.

플랫폼이 카디널 번호와 대수 링에 대해 별도의 유형을 완전히 지원하는 경우 카디널 번호 유형 (및 링 유형을 사용하여 랩핑 해야하는 항목)을 사용하여 카디널 번호를 처리해야한다고 제안합니다. 이러한 유형은 부호있는 유형의 두 배 크기로 숫자를 저장할 수있을뿐만 아니라 그러한 유형의 매개 변수를받는 메소드는 음수인지 여부를 확인할 필요가 없습니다.

그러나 기수-숫자 유형이 상대적으로 부족하기 때문에 일반적으로 정수를 사용하여 수학 정수와 기수를 모두 나타내는 것이 가장 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.