특정 유형이 여전히 필요합니까?


20

다른 날에 나에게 일어난 한 가지 일은 여전히 ​​필요한 특정 유형이나 우리를 방해하는 유산입니다. 내 말은 : 짧고 int, long, bigint 등이 실제로 필요합니까?

추론, 변수 / 객체가 메모리에 유지되고 메모리를 할당해야하므로 변수가 얼마나 클 수 있는지 알아야합니다. 그러나 실제로 현대의 프로그래밍 언어가 "적응 형"을 처리 할 수 ​​없어야합니다. 즉, 짧은 범위 내에서만 할당 된 경우 더 적은 바이트를 사용하고 갑자기 할당 된 경우 매우 큰 수의 메모리가 할당됩니다 특정 인스턴스에 맞게

float, real 및 double은 유형이 필요한 정밀도에 따라 달라지기 때문에 조금 까다 롭습니다. 그러나 문자열은 대부분 ascii가 사용되는 많은 인스턴스 (.Net)에서 메모리를 덜 차지할 수 있어야하지만 유니 코드 인코딩으로 인해 문자열은 항상 두 배의 메모리를 차지합니다.

특정 유형에 대한 한 가지 주장은 사양의 일부라는 것입니다. 예를 들어 변수가 특정 값보다 클 수 없어서 shortint로 설정해야합니다. 그러나 왜 타입 제약이 없는가? 변수 (및 속성)에 허용 범위 및 값을 설정할 수있는 것이 훨씬 유연하고 강력합니다.

기본 아키텍처와 긴밀하게 통합되어 직렬화와 같은 것이 실제로 까다로워 질 수 있기 때문에 유형 아키텍처를 개선하는 데 엄청난 문제가 있음을 알고 있습니다. 그러나 프로그래밍 관점에서 볼 때, 그렇지 않을까요?


6
PHP, Ruby, Perl 등은 변수 유형을 명시하지 않아도됩니다. 환경은 당신을 위해 그것을 알아냅니다.
FrustratedWithFormsDesigner

7
유니 코드 문자열은 ASCII 전용 (UTF-8)에만 사용될 때 추가 메모리를 사용할 필요가 없습니다.

2
그러나 변형 유형과 적응 유형 IMO에는 차이가 있습니다. 변형 유형은 전혀 입력되지 않지만 할당되면 입력되지만 적응 유형은 입력되지만 더 느슨합니다. (그리고 나는 타입 제약의 개념을 좋아한다)
Homde

이이 프로젝트를 생각 나게 : tom.lokhorst.eu/media/...
LennyProgrammers

4
에이다는 어떻습니까? type hour is range 0 .. 23;
mouviciel

답변:


12

나는 이것이 사실이라고 전적으로 믿는다. 시맨틱 제약은 구현 제약보다 더 가치가있다. 무언가의 크기에 대해 걱정하는 것은 객체 지향 프로그래밍이 시작될 때 무언가의 속도에 대해 걱정하는 것처럼 느껴집니다.

성능이 중요한 프로그래밍을 대체하지 않았습니다. 단지 성능이 중요하지 않은 프로그래밍을보다 생산적으로 만들었습니다.


1
.NET 4.0에서 코드 계약 을 확인하십시오 .
Steven Jeuris

+1 데이터 저장 / 전송 (예 : 네트워킹)과 관련하여 제약 조건은 프로토콜 / 구현의 효율성을 극대화하는 데 기본이됩니다. 또한 형식화 된 컬렉션을 사용할 수 있으면 얻을 수있는 많은 근거가 있습니다. 그 외에는 효율성이 뒷좌석을 취할 수 있다고 가정하는 것이 안전합니다 (특히 의미 오류의 가능성을 줄이는 경우).
Evan Plaice

9

적응 형 유형은 적응을 수행하는 로직을 의미하며 런타임시 해당 로직을 실행하는 작업을 의미합니다 (템플릿 및 컴파일 타임에는 특정 유형이 필요합니다. 유형 유추 는 두 가지 이점을 최대한 활용하는 특별한 경우입니다). 성능이 중요하지 않고 시스템이 적당한 크기를 유지하는 환경에서는 추가 작업이 문제가되지 않습니다. 다른 환경에서는 그렇지 않습니다 (내장 시스템은 CPU 성능을 위해 32/64 비트 정수 유형을 사용하고 정적 메모리 백업 최적화를 위해 8/16 비트 정수 유형을 사용해야하는 시스템입니다).

늦은 바인딩 (VB6과 같은 런타임시 형식의 해상도) 을 지원하는 범용 언어조차도 늦은 바인딩이 악용 될 때 발생했던 성능 저하로 인해 강력한 타이핑 (VB.NET)을 권장하는 경향이 있으며 유형이 명시 적이 지 않으면 못생긴 코드로 끝납니다 ( Visual Basic의 Reference / Professional 리팩토링-Danijel Arsenovski ).


"자동 입력"을 정의하십시오.

@delnan : 자동 타이핑을 늦은 바인딩으로 대체했습니다. :)
Matthieu

런타임에 유형을 해석하는 범용 언어가 많이 있으며 Common Lisp는 이름을 하나만 지정합니다. (당신은 단지 성능이 중요한 부분에서 그렇게 할 수 있도록 성능을 위해, 당신은, 커먼 리스프의 유형을 선언 할 수 있습니다.)
데이빗 쏜리

@David Thornley : "강화"강력한 타이핑이 너무 강력했을 수 있습니다. "프로모션"이 더 적절할 것입니다. 상황에 따라 두 종류의 바인딩 중 하나를 선택할 수있는 언어가 어떤 식 으로든 강제로 사용하는 것보다 확실히 좋습니다. 특히 저수준 프로그래밍을하지 않고 로직에 집중할 때.
Matthieu 2019

4

단순성, 메모리 및 속도 변수를 선언하면 해당 변수의 메모리가 한 블록에 할당됩니다. 동적으로 성장하는 변수를 지원하려면 비 연속 메모리 개념을 해당 변수에 추가해야합니다 (또는 변수가 나타낼 수있는 가장 큰 블록을 예약). 연속되지 않은 메모리는 할당 / 검색시 성능을 저하시킵니다. 바이트가 필요하지만 시스템이 오랫동안 예약하는 시나리오에서 가능한 가장 큰 할당은 낭비가됩니다.

배열과 벡터 (또는 연결된 목록) 사이의 장단점을 생각해보십시오. 배열을 사용하면 특정 위치를 찾는 것은 시작 위치를 가져와 메모리에서 x 위치를 이동하여 메모리에서 해당 새 위치를 찾는 간단한 문제입니다. int를 비트 [32]로 읽는 것은 int를 읽는 것은 모든 비트 값을 얻기 위해 해당 배열을 걷는 것을 포함합니다.

동적 숫자 유형을 만들려면 비트 배열에서 비트 벡터로 변경해야합니다. 동적 번호를 읽으려면 헤드로 이동하여 해당 비트를 가져오고 다음 비트가 메모리에있는 위치를 묻고 해당 위치로 이동하고 해당 비트를 가져 오는 등의 작업을 수행해야합니다. 현재), 읽기 (다음 주소), 이동 (다음). 백만 개의 숫자 값을 읽는다고 상상해보십시오. 그것은 백만 개의 추가 작업입니다. 중요하지 않은 것 같습니다. 그러나 1 밀리 초마다 중요한 시스템 (예 : 재무)에 대해 생각하십시오.

크기를 확인하고 유효성을 검사하도록 개발자에게 책임을지는 것은 시스템 성능에 영향을 미치는 것과 비교하여 작은 절충안이라는 결정이 내려졌습니다.


1
다른 대안은 숫자가 현재 크기보다 커질 때 배열이 다시 할당되는 배열 목록과 유사한 숫자를 구현하는 것입니다. 또한 사용자가 오버플로 루프를 WANTS하는 경우를 고려해야합니다.
Michael Brown

사실이지만 다소 단순화 된 것입니다. 정적 인 유형만큼 빠르지는 않지만 대부분의 경우 "충분히 빠를"수는 있지만보다 효율적인 배열 구조를 생각해 낼 수 있습니다. 예를 들어, 배열이 완전히 들쭉날쭉하지 않아서 더 많은 메모리 나 성능을 차지하지 않는 다른 유형의 블록에 정보를 저장할 수 있습니다. 또는 배열이 어떤 종류의 인덱스를 갖기 위해 일부 메모리를 희생시킬 수 있습니다. 배열은 내용에 따라 자체 최적화 할 수도 있습니다. 성능이 필요한 경우 유형 제약 조건을 통해 메모리 크기를 입력하는 옵션을 여전히 사용할 수 있습니다.
Homde

공정하게 말하자면, 당신이 만드는 것만 큼 잔인하지 않습니다. Cf 내 다가오는 대답.
Paul Nathan

3

하드웨어 중심 언어 및 프로젝트에는 특정 유형이 필요합니다. 한 가지 예는 무선 네트워크 프로토콜입니다.

그러나 재미있게 C ++과 같은 언어로 varint 유형을 만들어 봅시다. new'd 배열의 정수로 빌드하십시오 .

추가를 구현하는 것은 어렵지 않습니다. 바이트를 xor로 묶고 높은 비트를 확인하십시오. 캐리 연산이 있으면 new새로운 상위 바이트에서 비트 오버를 수행하십시오. 뺄셈은 2의 보수 표현에서 사소하게 따릅니다. (이것은 리플 캐리 가산기로도 알려져 있습니다).

곱셈도 비슷하게 따른다. 반복적 인 추가 / 이동을 사용하십시오. 항상 그렇듯이 꼬리의 실제 비틀림은 나눗셈입니다 [*].

그래도 이런 일이 생기면 무엇을 잃어 버리나요?

  • 결정적인 시간. new반드시 제어 할 수없는 지점에서 트리거 할 수 있는 syscall ( )이 있습니다.

  • 결정 론적 공간.

  • 반 소프트웨어 수학이 느립니다.

하드웨어 계층 언어를 사용해야하고 높은 수준 (느린) 수준에서 작동해야 하고 스크립팅 엔진을 포함 하고 싶지 않은varint 경우 많은 의미가 있습니다. 아마 어딘가에 쓰여졌을 것입니다.

[*] 더 빠른 방법을위한 Cf 하드웨어 수학 알고리즘-일반적으로 트릭은 병렬 연산입니다.


2

좋은 질문입니다. 파이썬과 같은 언어가 "short, int, long, bigint 등"을 필요로하지 않는 이유를 설명합니다 : 정수는 정수입니다 (Python 3에는 단일 정수 유형이 있음). 물론 컴퓨터의 메모리).

유니 코드의 경우 UTF-8 인코딩 (유니 코드의 일부)은 ASCII 문자에 단일 문자 만 사용하므로 그렇게 나쁘지는 않습니다.

더 일반적으로, 동적 언어는 언급 한 방향으로 진행되는 것 같습니다. 그러나 효율성을 위해 일부 경우에 더 제한적인 유형이 유용합니다 (예 : 빠르게 실행되어야하는 프로그램). 프로세서가 바이트 (또는 2, 4, 8 등) 바이트 단위로 데이터를 구성하므로 예측 가능한 미래에는 큰 변화가 없습니다.


1

언어 이론에 따라 당신이 맞습니다. 유형은 일련의 법적 상태, 해당 상태에서 사용 가능한 변환 및 해당 상태에서 수행 할 수있는 작업을 기반으로해야합니다.

그러나 이것은 일반적인 형태의 OOP 프로그래밍이 제공하는 것입니다. 실제로 Java에서는 객체를 저장하는 데 필요한 양에 따라 공간을 할당하는 클래스 BigIntegerBigDecimal클래스 에 대해 효과적으로 이야기 하고 있습니다. (FrustratedWithFormsDesigner가 지적했듯이, 많은 스크립팅 유형 언어는이 경로를 따라 더 나아가 있으며 유형 선언조차 필요 없으며 사용자가 제공 한 모든 것을 저장할 것입니다.)

그러나 성능은 여전히 ​​관련성이 있으며 런타임에 유형을 전환하는 데 비용이 많이 들고 컴파일러는 컴파일 타임에 변수의 최대 크기를 보장 할 수 없으므로 여러 언어로 된 간단한 유형에 대한 정적 크기 변수가 여전히 있습니다.


나는 어떤 종류의 동적 / 적응 형 타이핑이 현재의 것보다 비용이 많이 들고 성능이 떨어지는 것처럼 보이며 현재 컴파일러를 사용하는 것이 확실합니다. 그러나 우리가 처음부터 언어와 컴파일러를 빌드하면 정적 타입만큼 빠르지는 않지만 가치가있을 정도로 빠르지 않다는 것을 100 % 확신합니다.
Homde

1
@MKO : 시도해 보지 않겠습니까?
아논.

1
그렇습니다. 아마도 빠른 속도로 만들 수는 있지만 숫자에 대한 정적 시스템만큼 빠르지는 않습니다. 그러나 "가치가있는"부분은 더 까다 롭습니다. 대부분의 사람들은 범위가 inta 또는 a 에 편안하게 맞는 데이터를 사용 하며 double, 그렇지 않은 경우이를 알고 있으므로 동적 값 크기 조정은 비용을 지불 할 필요가없는 기능입니다.
jprete

물론 모든 프로그래머로서 나는 언젠가 내 언어를 만드는 꿈을 꾼다.)
Homde

@ jprete : 동의하지 않습니다; 대부분의 사람들은 가능한 큰 중간 결과를 알지 못합니다. 이러한 언어는 대부분의 목적을 위해 충분히 빠르게 만들어 질 수있었습니다.
David Thornley

1

언어에 따라 다릅니다. Python, Ruby, Erlang 등과 같은 고급 언어의 경우 정수와 십진수의 개념 만 있습니다.

그러나 이러한 유형의 특정 언어 클래스에는 매우 중요합니다. PNG, JPeg 등과 같은 이진 형식을 읽고 쓰는 코드를 작성할 때 한 번에 읽는 정보의 양을 정확하게 알아야합니다. 운영 체제 커널 및 장치 드라이버 작성과 동일합니다. 모든 사람이이 작업을 수행하는 것은 아니며 고급 언어에서는 C 라이브러리를 사용하여 세부적인 작업을 수행합니다.

에는 short여전히 더 구체적인 유형을위한 장소가 있지만 많은 개발 문제는 그러한 정밀도를 요구하지 않습니다.


0

최근에 래더 로직 편집기와 런타임을 만들었으며 유형에 따라 매우 제한적이라고 결정했습니다.

  • 부울
  • 번호
  • 날짜 시간

사용자에게 더 직관적이라고 생각합니다. 이것은 C와 같은 언어로 볼 수있는 모든 "일반적인"범위의 유형을 가진 대부분의 PLC와는 근본적으로 다릅니다.


0

프로그래밍 언어가 그 방향으로 움직이고 있습니다. 예를 들어 문자열을 사용하십시오. 이전 언어에서는 PIC X(42)COBOL 과 같이 DIM A$(42)일부 버전의 BASIC 또는 [ VAR] CHAR(42)에서 SQL 의 문자열 크기를 선언해야합니다 . 현대 언어에서는 동적으로 할당 된 string유형 이 하나만 있으며 크기를 생각할 필요가 없습니다.

그러나 정수는 다릅니다.

내 말은 : 짧고 int, long, bigint 등이 실제로 필요합니까?

파이썬을 살펴보십시오. 기계 크기 ( int)와 임의 크기 ( long)의 정수 를 구별하는 데 사용되었습니다 . 3.x에서 전자는 사라졌고 (오래된 long것은 새로운 것입니다 int) 아무도 그것을 놓치지 않습니다.

그러나 여전히위한 특수한 유형의 거기 시퀀스 의 형태로 8 비트 정수 bytesbytearray. 왜 사용하지 tuple또는 list각각의 정수를? 사실, bytes그렇지 않은 추가 문자열과 같은 방법이 tuple있지만 효율성은 분명히 관련이 있습니다.

float, real 및 double은 유형이 필요한 정밀도에 따라 달라지기 때문에 조금 까다 롭습니다.

실제로는 아닙니다. "모든 것이 배정 밀도입니다"접근 방식은 매우 일반적입니다.


1
기본 유형은 유형의 기본 의도, 즉 "일반"숫자의 int, 모든 일반 "소수"의 두 배를 선언해야합니다 (간결성을 위해 ints는 소수를 가질 수 없습니까?) 이진 데이터 작업에 사용됩니다. 속성을 통해 선언 된 형식 제약 조건은 허용 범위, 십진 정밀도, Null 허용 및 허용 된 값을 선언 할 수 있습니다. 그런 식으로 사용자 정의 및 재사용 가능한 유형을 만들 수 있다면
멋질

@konrad : IMHO, "부호없는"정수로 인해 C에서 두통이 발생하는 이유는 때때로 숫자 를 나타내는 데 사용되며 때로는 래핑 추상 대수 고리의 멤버를 나타내는 데 사용되기 때문입니다. 별도의 "ring"및 "unsigned number"유형을 사용 unum64 += ring32a-ring32b하면 기본 정수 유형이 16 비트 또는 64인지에 관계없이 이와 같은 코드 가 항상 올바른 동작을 수행 할 수 있습니다 +=. 같은 표현 unum64a = unum64b + (ring32a-ring32b);은 모호한 것으로 거부되어야한다.]
supercat

0

추론, 변수 / 객체가 메모리에 유지되고 메모리를 할당해야하므로 변수가 얼마나 클 수 있는지 알아야합니다. 그러나 실제로 현대의 프로그래밍 언어가 "적응 형"을 처리 할 수 ​​없어야합니다. 즉, 짧은 범위 내에서만 할당 된 경우 더 적은 바이트를 사용하고 갑자기 할당 된 경우 매우 큰 수의 메모리가 할당됩니다 특정 인스턴스에 맞게

float, real 및 double은 유형이 필요한 정밀도에 따라 달라지기 때문에 조금 까다 롭습니다. 그러나 문자열은 대부분 ascii가 사용되는 많은 인스턴스 (.Net)에서 메모리를 덜 차지할 수 있어야하지만 유니 코드 인코딩으로 인해 문자열은 항상 두 배의 메모리를 차지합니다.

Fortran은 비슷한 것을 가지고 있습니다 (실제로 두 가지 질문을보고 있기 때문에 이것이 정확히 무엇을 의미하는지는 알 수 없습니다). 예를 들어, F90 이상에서는 유형 size 를 명시 적으로 정의 할 필요가 없습니다 . 데이터 유형을 정의하는 중앙 위치뿐만 아니라 데이터 유형을 정의하는 이식 가능한 방법을 제공하기 때문에 좋습니다. REAL * 4는 모든 프로세서 (및 프로세서에 따라 CPU + 컴파일러를 의미 함)의 모든 구현에서 동일하지는 않습니다.

selected_real_kind (p, r) 는 10 자리 이상의 정밀도와 p 이상의 지수 범위를 갖는 실제 데이터 유형의 종류 값을 반환합니다.

예를 들어,

program real_kinds
integer,parameter :: p6 = selected_real_kind(6)
integer,parameter :: p10r100 = selected_real_kind(10,100) !p is precision, r is range
integer,parameter :: r400 = selected_real_kind(r=400)
real(kind=p6) :: x
real(kind=p10r100) :: y
real(kind=r400) :: z

print *, precision(x), range(x)
print *, precision(y), range(y)
print *, precision(z), range(z)
end program real_kinds

(나는 그것이 자기 설명 적 예라고 생각한다).

여전히 귀하의 질문을 올바르게 이해했는지 여부를 알 수 없으며 이것이 귀하의 의견입니다.

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