pascal 은 기본적으로 1부터 시작하고 있고, 배열 인덱스를 재배치 할 수도 있다 (시작을 음수로도 지정 가능)

C의 포인터를 이용하면 역시 음수 index를 사용할 수는 있지.


ex)

#define RADIUS 1000

#define RAD2DIA_DREG 1

#define DIAMETER (RADIUS * 2 + RAD2DIA_DREG)

int pixelsInSin[DIAMETER];

int* centerInPixels = pixelsInSin + RADIUS;


위의 예는 픽셀의 단위에서 중앙이 픽셀과 픽셀 사이에 위치하는 애매함을 해결하기 위해

지름이 반지름 * 2 + 1 이 되는 아름답지 않은 상황을 반영한 것.

이 코드에서 우리는 centerInPixels[-RADIUS] 부터 centerInPixels[RADIUS] 까지 접근 할 수 있다.

sin, cos 같은류의 -1 ~ +1 범위 연산을 수행하기 적합한 코드지.


자연수의 정의는 0을 포함하기도 하고(집합론) 포함하지 않기도 한다.

집합론에서 0의 정의는 null 이고, (의미적으로 nothing 이 아니다. no something 이다. 우주는 무의 공간이 아니거든)

1의 정의는 {null} // something

인데 반해

2의 정의는 {{null}, {null}} 또는 (수론으로 연결됨)

{null, {null}} (집합론, 경우의 수를 센 정보량적 표현)

로 표현되는 것과 같은 이치다.


이런 문제는 min to max 의 범위 문제로 이어지는데,

정규화 시킨 0 ~ 1 의 범위가 scaling 과 같은 transform 에 가장 아름답지만,

주기성의 out of bound 를 clamp 할 수 있는 나머지 연산(%) 은 range - 1 의 결과를 얻기에

rand() 류의 함수 역시 범위 - 1 의 max 를 갖는다.


조금 말이 어렵지?


우리는 우리의 문제와 해결방법을 다양한 용도에 사용될 수 있게 하기 위해 정규화를 해야한다.

가령 20~50 범위의 입력을 10 ~ 100 범위의 출력으로 바꾸고 싶다는 것 과같은 transform 을 자주 구현하게 되는데

이럴 때, 네 가지 일반적 단계를 거치게 된다.


1. min을 0점으로 이동 (min의 normalize)

2. max를 1로 바꿈 (max의 normalize)

3. 스케일링 (size 의 reflection)

4. 결과점(원점)으로 이동 (position 의 reflection)


위의 단계대로 20~50 을 10~100 으로 바꾸어 보면


1. 입력 - 20 을 해서 0~30 범위를 얻는다

2. 30으로 나누어 0~1 범위를 얻는다

3. 90으로 곱하여 0~90 범위를 얻는다

4. +10 해서 10~100 범위를 얻는다


로 전개 되는 것이다.


이 예는 특별한게 아니다.

RGB 의 각 색상 콤포넌트의 범위를 0~255 로 정의하는 시스템도 있고 0~1로 정의하는 시스템도 있다.

0~1로 정규화해서 표현하지 않고 MAX를 0.9 나 0.99 0.999 로 표현한다면 얼마나 바보같을지 생각해 봐라. 우습지만 그런 시스템 흔하다.

만약 누군가 0~255 의 RGB 색상 공간을 0~65535 의 sRGB 색상공간이나 0~15 의 색상공간으로 변환하는 일을 빈번하게 수행한다고 가정하자.

정규화를 하지 않으면 변환 전의 format 을 사용해 나올 수 있는 경우의 수를 모두 구현해야 한다.

outputComponent = inputComponent / inputMax * outputMax

하지만 입력(inputComponent)을 0~1로 변환한 다음이라면,

outputComponent = inputComponent * outputMax

이렇게 간단히 outputMax의 곱셈만 수행하면 되고 변환 전의 format 을 기억할 필요가 없다.


여기서 내가 말하고자 하는것은 한가지다.

min을 1로 하여 자연수 max 를 표현하면 max == range 가 되어 우선 깔끔해 보이지만,

0도 1도 무척 중요하고 정규화라는 편의성을 제공해주기 때문에 Max 를 Range 로 두는건 뒷단에서의 노가다를 감수해야하는거다.


자기 코드 안에 이곳은 수론 저곳은 집합론의 표현으로 구현해두면 헷갈릴 수 밖에 없겠지.

/*

대부분의 시스템에서 max는 range 일 수 없다.

dreg 는 서로 다른 시스템간의 변환에서 사람의 인식을 돕기위해서나 위치를 존재하게 하기 위한 필요악이다.

우리는 흔히 dreg 문제를 해결하기 위해 반올림이나 버림 따위의 애매한 선택을 하기도 하고,

그 애매한 선택은 프로젝트 종료까지 너를 따라다닐거다. 어쩌면 영영 아쉬움으로 남을 수도 있고.

min 이 1이 되는 시스템이 많을 것 같냐?

하지만 min을 0으로 두면 어느방향으로든 나아가기 쉽다.

정규화를 통해 max를 1로 두면 아름답다. 그말은 많은 곳에 유용하게 쓰인다는거다.

1보다 작은 소숫점으로 나누면 1보다 큰 자연수를 곱하는 효과니까 -1. ~ +1 의 영역이 hot spot 이란거다.

삼각함수의 좁은각 특성이나 테일러 급수를 이용한 최적화에 이용하더라도 유리한 공간임엔 틀림없다.

*/


두 줄 요약.

위의 4가지 step 에서 1번이라도 수행하지 않을 수 있게 해주기 위해 0부터 시작하는 index 가 여러모로 유용하다고 생각.

어디까지나 개인 취향의 문제로 보이지만, 시작을 저렇게 해두지 않으면 뒤에서 늘어나는 코드와 수고는 자기 책임이다.