프로그래밍 독학 중 질문

  • #3370157
    12345 69.***.33.212 1006

    이런 페이지가 나왔는데 인터넷으로 간단하게 설명된 동영상을 찾아보려고 합니다.
    symmetric, asymmetic 이해가 잘 안가는데
    찾아보니 너무 광범위해서 …. 어떤 키워드로 찾아보면 될지 혹시 알 수 있을까요….
    감사합니다.

    Choose Loop Bounds That Match Your Task

    Suppose you want to print line numbers that go from 1 to 10. Of course, you will want to use a loop

    for (int i = 1; i <= 10; i++)
    The values for i are bounded by the relation 1 ≤ i ≤ 10. Because there are ≤ on both bounds, the bounds are called symmetric.

    When traversing the characters in a string, it is more natural to use the bounds

    for (int i = 0; i < str.length(); i++)
    In this loop, i traverses all valid positions in the string. You can access the ith character as str.substr(i, 1). The values for i are bounded by 0 ≤ i < str.length(), with a ≤ to the left and a < to the right. That is appropriate, because str.length() is not a valid position. Such bounds are called asymmetric.

    In this case, it is not a good idea to use symmetric bounds:

    for (int i = 0; i <= str.length() – 1; i++) // Use < instead
    The asymmetric form is easier to understand.

    • 어레이 98.***.115.123

      용어에 현혹되지 마세요. 그냥 뭔가 있어 보이려고 쓴 말에 불과합니다.
      도형이 대칭이냐 아니냐에 쓰는 말을 어레이 인덱싱에 쓰니까 초보자들이 헷갈려 하는 것입니다.

      어레이라는 자료 구조를 이용할 때, indexing 을 1부터 하는 언어도 있고, 필요에 의해 그런 방법으로 프로그램 하는 경우도 있습니다.
      그런 경우 마지막 element는 arr.length()와 같아 지게 됩니다.

      하지만 C,C++ 처럼 0부터 indexing하는 언어의 경우 마지막 element는 전체 갯수 -1 이 되어야 하기 때문에
      처음 과 같이 마지막 조건(그런 이류로 대칭이라는 말을 쓴거 같습니다)을 i<=str.length()하면 에러 납니다.
      마지막 조건을 i < str.length() 로 하느냐 i <= str.length-1 로 하느냐의 차이인데…
      i < str.length() 하는게 더 좋습니다. 왜냐하면 계산을 한 번이라도 덜 하고 이해하기가 편하기 때문입니다.

    • abc 211.***.88.34

      쉬운 개념을 어렵게 설명하네요. 교재나 강의 바꾸시는게 좋을 것 같습니다.

      for statement는 (초기화, 루프가 지속되는 조건, 변수에의 조작) 이렇게 세 부분으로 이루어집니다.

      당연히 안에 뭘 넣을지는 프로그래머 마음인데,
      배열에 접근할 때는 0 ~ n-1을 순회하는 경우가 매우 많습니다.

      그러면 코드를 쓸 수 있는 방법이 두 가지죠.
      1. for (int i = 0; i <= n-1; ++i)
      2. for (int i = 0; i < n; ++i)

      이 중 2번이 더 직관적이니 2번을 사용하라는 겁니다. 저렇게 표현하는 습관을 들이면, for statement를 보기만 해도 0.1초 안에 n번 수행되겠구나 하고 견적이 나오겠죠.

    • A5 32.***.155.94

      그걸로 공부하지 마세요.
      어떤 책은 우리에게 맞지 않게 쓰여저 있습니다.
      C++라면, the c++ programming language(Stroustrup)란 책을 추천합니다.

    • 73.***.55.47

      한자섞인 성문 영어 문법책으로 영어공부하는 느낌이군요.

    • embedded guy 64.***.218.106

      책의 저자도 아마 다른 책에서 보고 베낀듯한 느낌이 나는군요. 프로그래밍에서 말하는 루프란 흔히 for, while 같은 반복되는 작업을 처리하는 문법을 통칭해서 말하는겁니다. 극도로 단순하고 무슨 다른 개념이 있는것도 아닙니다.

      책의 저자가 지적하는 부분은 아마도 루프문을 쓸때 흔히 저지르는 실수를 예방하기 위한 팁같은것처럼 보이는군요. 실제로 배열을 처리할때 어디까지 배열을 검색해야하는지 정확히 말하자면 배열의 유의미한 마지막 엘리먼트의 위치가 어딘지 혹은 마지막 엘리먼트를 넘어가서 메모리 바이올레이션을 저지르지 않는것은 매우 중요합니다. 특히 가변 문자열을 배열에 저장하고 처리하는 경우 에러 케이스를 항상 체크하고 배열을 다시 리셋하고 하는 과정들이 사실 어려운게 아니라 실수를 자주 합니다. 바로 레인지 설정 때문에요. 하지만 저자가 말하는 용어는 그런것과는 무관하게 쓴것 같으니 별 신경안쓰셔도 될듯…

    • 12345 69.***.33.212

      감사합니다.

    • T 74.***.192.199

      “The asymmetric form is easier to understand.”

      저자의 마지막 문장에 대해 약간 설명을 해야겠네요. 이 문장은

      “The asymmetric form is easier (for others) to understand.”

      라고 이해해야 합니다. 지금 독학 중이신 본인에게 더 이해하기 쉽다는 뜻이 아니에요. others에게 이해하기 쉬우면 나에게도 쉽다는 뜻이 아닌가라고 생각하실 수도 있지만 그렇지 않습니다.

      저자가 looping의 형태가 왜 저렇게 되었는지 그 기원을 몰라서 후자가 더 이해하기 쉽다고 잘못 주장하는 것입니다.

      루핑 그 자체에서는 전자가 사실 더 직관적입니다. 후자는 부자연스럽지만 연습을 통해 현대의 모든 프로그래머가 익숙해져야 하는 루핑의 형태입니다. 이해하기 더 쉬워서 많이 쓰는 게 아닙니다.

      루핑을 하는 목적을 보면, 전자는 카운팅을 하는 것이고 후자는 연속된 데이터 액세스를 위한 offset(배열의 첫 데이터에서 N 번째 데이터까지의 거리)을 만들어내는 것입니다. i라는 변수의 용도가 그렇다는 것이죠. 10회 루핑을 할 때 10회 카운팅이 목적일 수도 있고, 10개의 연속된 데이터 액세스가 목적일 수도 있습니다. 카운팅 용도로만 쓸 때는 (예를 들어 Hello World를 10번 출력하는 등) 변수의 시작이 2에서 시작해서 11에서 끝나도 되지만 (하지면 사람의 관습은 카운팅은 1부터 시작하니까 보통 1부터 10까지 세겠죠). 하지만 연속된 데이터 액세스가 목적일 때는 offset이 필요하고, offset은 항상 0에서 시작하니까 10번 반복하려면 offset 값이 0 에서 9까지 변하도록 루핑 바운더리 조건을 “잘” 만들어줘야 해요. 이 “잘” 만드는 부분이 자연스럽지 않기 때문에 수많은 초보 프로그래머들이 루핑에서 실수를 합니다. 이해하기 쉽지도 않죠.

      그 기원을 보면, 50여년전 machine language나 assembly 언어를 다루던 시절에 메모리의 연속 데이터를 읽기 위해서 base address와 offset을 저장하는 (레지스터라고 불리는) 변수 두 개를 이용했는데요. 루핑을 시작할 때 base address는 이미 첫 데이터를 가리키고 있기 때문에 offset의 첫 값도 0이어야 제대로 첫 데이터를 액세스 할 수 있었죠. 그런식으로 offset이 9가 되면 10번째 데이터가 액세스 되는 식이죠.

      그 유산을 물려받아 C 언어가 디자인될 때, 사람에게는 자연스럽지 않지만 코드량을 약간 더 줄여주는 이 방식을 그대로 채택을 했습니다. C언어의 디자인 정신이 machine language의 컴팩트함과 효율성을 그대로 발휘할 수 있게 해주자는 것이어서 말이 됐죠.

      그 후 C 언어가 대성공을 거두고 광범위하게 퍼져서, C언어의 형태를 상속한 C++, .Net, Java, JavaScript 등 현 세대의 많은 프로그래밍 언어가 같은 방식의 루핑을 사용합니다.

      수십년간 많은 프로그래머들이 for (int i = 1; i <= 10; i++) 와 같이 써서 핀잔을 듣거나 (이렇게 루핑을 하면 컴퓨터 내부 구조를 잘 모르는 초보로 간주되었죠) for (int i = 0; i <= 10; i++) 과 같이 써서 버그를 만들어내고 하는 소동을 각자 거치며 결국 for (int i = 0; i < 10; i++) 의 형태에 본인들이 익숙해지게 됩니다. 그리고 그것이 연속된 데이터를 액세스 하는 최적의 machine 코드를 만들어내도록 compiler를 돕는 길이라는 것을 학습하게 됩니다. 그런 학습과 연습 과정을 다 거치고 훈련이 끝난 프로그래머는 for (int i = 0; i < 10; i++) 형태를 연속된 데이터를 액세스 할 때 당연히 사용하지만 또한 카운팅을 할 때도 사용하죠. 남의 코드에서 그런 형태를 보면 즉시 10번 루핑이라는 것도 물론 금방 알아봅니다.

      다시 돌아가서 저자가 말한 마지막 문장은 다른 모든 프로그래머가 훈련을 통해 이미 그 형태에 익숙해진 상태이고 이미 쓰여진 수백억 줄의 코드가 그런 형태를 하고 있으니, 지금 배우는 독자들이 다른 프로그래머들이 쓴 코드를 편하게 보려면 그 형태가 편하다고 느껴질 때까지 훈련해야 한다… 는 의미로 이해하셔야 하고, 또 본인에게 지금은 자연스럽지 않더라도 계속 그렇게 써야 다른 프로그래머들이 본인의 코드를 볼 때 루핑의 횟수를 금방 알아봅니다.

      마지막 문장에서 “너 이게 더 쉽게 느껴지지 않는다면 니가 바보야” 라는 느낌을 받으실까 염려되어 길게 써봤습니다. 저자가 나빴어요.