1. Introduction
LOGO 중급 - repCount - 001 연습 예제입니다. 변수, 파라미터 변수, repCount 등을 이해할 수 있어야 합니다. boxes 함수의 lt :A 부분이 핵심입니다. 우연 효과 혹은 LOGO Bug? (텍스트 표시 라벨 부분은 일단 무시하세요.)
2. Code
to box1 :side
repeat 4 [ fd :side rt 90 ]
end
to boxes
repeat 1800 [
box1 :side pu rt 90 fd :side+5 lt 90
make "A repCount + 0.7
lt :A pd
]
end
to displayText
gotoCenter
text1
gotoNextLine
text2
end
to draw
boxes
displayText
HT
end
to gotoCenter
pu lt 90 fd 270 rt 90 fd 150 pd
end
to gotoNextLine
pu back 30 pd
end
to main
setup
draw
end
to setup
Window Home CS PPT PD ST
pu rt 90 fd 150 lt 90 back 120 pd
make "side 10
make "A 0
end
to text1
rt 90
label [ "YS is BABO! ^.^ ..." ]
lt 90
end
to text2
rt 90
label [ "SH is BABO too! ^.^ ..." ]
lt 90
end
3. Result
4. Notes
boxes 함수의 lt :A 부분이 핵심입니다.
make "A repCount + 0.7
lt :A pd
위 코드가 어떻게 해서 회전체를 만들어내는지 생각해보세요. repCount 값에다가 0.7을 더해서 A에 저장합니다. 여기서 repCount 값은 1부터 반복횟수 1800까지 자동 증가합니다.
repCount는 LOGO의 내장 특수 변수라서 변수명 앞에 콜론(:)을 사용하지 않습니다. repCount는 현재의 반복 횟수를 카운트하는 용도로 사용됩니다. 이 변수는 반복할 내용이 반복될 때마다 1씩 증가합니다. 처음에는 1부터 시작합니다.
0.7 증가폭으로 LT 회전각을 0.7 증가폭으로 1800회 반복하면 중간에 어떤 일이 발생하게 될까요?
1800 * 0.7 = 1260.
원과 같이 완전한 1회전에는 LT 360도면 충분합니다. 그런데 1260이나 주어지는군요. 대략 360의 3.5배 정도입니다.
■ Q1. 이 0.7을 제거하고 반복 횟수를 1800에서 720정도로 줄여서 테스트해보세요. 0.7이 제거된 상태에서 719와 720을 번갈아 가면서 테스트해보세요. 이 숫자 720에서 무엇을 알 수 있나요?
■ Q2. 그리고 0.7 이 값을 변경해서 다양한 테스트를 해보세요. 이 값의 역할은 무엇인가요?
■ 테스트 - 02
0.7 떼어내고 360회 반복 시 결과. 검은 블랙홀 속으로 들어갔다가 나오면서 LT가 RT로 바뀐 느낌? ^.^;
( 뭔가 음수값으로 전환된 느낌? FD -100 또는 LT -45 같은 ... )
to boxes
repeat 360 [
box1 :side pu rt 90 fd :side+5 lt 90
make "A repCount
lt :A pd
show [ repCount : ] Show repCount
; 테스트 용으로 사용
show [ :A ] show :A
; show 명령은 제법 delay가 발생함.
]
end
■ Result ...
블랙홀 속으로 들어갔다가 나오면 방향이 바뀌는 듯 보입니다?? 왜??
■ 테스트 - 03
0.7 떼어내고 720회 반복 시 결과. 검은 블랙홀 속으로 들어갔다가 나오면서 LT가 RT로 바뀐 느낌? ^.^;
to boxes
repeat 720 [
box1 :side pu rt 90 fd :side+5 lt 90
make "A repCount
lt :A pd
show [ repCount : ] Show repCount
; 테스트 용으로 사용
show [ :A ] show :A
; show 명령은 제법 delay가 발생함.
]
end
■ Result ...
■ Q. CoPilot에게 FMSLogo 블랙홀 부분 그림을 보여주며 손가락으로 가리키며 이 부분 저부분 질문하기...
make "A repCount + 0.7
lt :A pd
CoPilot은 FMSLogo의 repcount 변수가 정수형이라고 합니다. 변수 A는 부동소수점을 더해서 부동소수점 타입이 되고. LT 명령어는 정수형 뿐만 아니라 부동소수점 값도 문제없이 처리할 수 있을 것이라고 합니다.
"...
A. 일반적으로 양수 값이 음수로 해석되는 경우는 드물지만, 데이터 형 변환이나 오버플로우와 같은 특정한 상황에서는 발생할 수 있습니다. 여기 몇 가지 예를 들어볼게요:
1) 데이터 형 변환: 정수의 크기가 제한된 데이터 타입을 사용할 때, 예를 들어 16비트 정수에서는 최대값이 32767이고, 최소값이 -32768입니다. 만약 최대값을 넘는 값을 저장하려고 하면 오버플로우가 발생할 수 있습니다. 이 경우, 양수 값이 음수로 해석될 수 있습니다.
import numpy as np
x = np.int16(32767 + 1)
print(x) # -32768이 출력됩니다.
2) 메모리 해석 문제: 비트 단위로 데이터를 해석할 때, 부호 비트를 잘못 해석하면 양수 값이 음수로 보일 수 있습니다. 예를 들어, 부호와 절대값 표현 (Sign-Magnitude Representation) 에서는 최상위 비트가 부호를 나타내므로, 이 비트를 잘못 읽으면 양수 값이 음수로 해석될 수 있습니다.
3) 2의 보수 표기법: 컴퓨터 시스템에서 음수를 표현하는 데 자주 사용되는 2의 보수 표기법에서도, 부호 비트를 포함한 전체 비트를 사용하여 음수 값을 표현합니다. 만약 이러한 비트를 잘못 해석하면 음수 값이 양수로, 혹은 양수 값이 음수로 해석될 수 있습니다.
def to_signed(n):
return n if n < 0x8000 else n - 0x10000
# 16비트 정수 값 0xFFFF는 -1로 해석됩니다.
signed_value = to_signed(0xFFFF)
print(signed_value) # -1 출력
(
□ 참고 :
return n if n < 0x8000 else n - 0x10000
# 위 표현에 쓰인 16진수 값들은 각각 십진수 32768, 십진수 65536. 타입 최대값들 비교 조건.
)
이러한 상황들은 주로 저수준 프로그래밍이나 시스템 프로그램에서 발생할 수 있습니다. 일반적인 고수준 프로그래밍 언어에서는 이러한 문제를 자동으로 처리해주기 때문에, 개발자가 직접적인 문제로 겪을 일은 많지 않습니다.
..."
"...
Logo 프로그래밍 환경에서 양수 값이 음수로 해석될 수 있는 경우는 매우 드뭅니다. 하지만 특정 상황에서는 데이터 형 변환이나 부호 비트의 잘못된 처리로 인해 이러한 문제가 발생할 수 있습니다. 다음은 Logo에서 발생할 수 있는 몇 가지 경우입니다:
- 큰 수의 사용: Logo는 일반적으로 큰 숫자를 처리할 수 있지만, 특정 환경이나 구현에서는 최대 처리 가능한 숫자가 제한될 수 있습니다. 이러한 경우 오버플로우가 발생할 수 있으며, 이로 인해 예상치 못한 결과가 나올 수 있습니다.
- 부동 소수점 연산: 부동 소수점 연산에서는 소수점 이하의 정밀도가 제한될 수 있습니다. 이로 인해 매우 큰 값이나 매우 작은 값을 처리할 때 부정확한 결과가 나타날 수 있으며, 이는 음수로 해석될 가능성도 있습니다.
- 저수준의 메모리 해석: Logo 자체는 고수준의 교육용 프로그래밍 언어로 설계되어 저수준의 메모리 관리 문제를 직접 다루지는 않지만, Logo 인터프리터나 컴파일러가 내부적으로 메모리를 어떻게 해석하느냐에 따라 이러한 문제가 발생할 수 있습니다.
- 변수 범위 및 타입: 특정 구현에서는 변수의 범위나 타입에 따라 값이 이상하게 변환될 수 있습니다. 예를 들어, 양수 값을 저장할 변수의 크기가 작다면 오버플로우가 발생할 수 있습니다.
전반적으로 Logo는 이러한 문제를 피할 수 있도록 설계된 고수준 언어이기 때문에, 일반적인 사용에서는 큰 문제가 발생하지 않습니다. 그러나 특정 상황에서는 예상치 못한 결과가 발생할 수 있음을 유념하시기 바랍니다.
..."
"...
A. 이해했습니다. 오버플로우는 특정한 상황에서 발생할 수 있는 문제입니다. 특히 반복 횟수가 매우 클 경우, 변수의 값이 최대치에 도달하면서 양수 값이 음수 값으로 변환될 수 있습니다. Logo에서는 이러한 문제를 방지하기 위해 변수의 범위를 잘 관리하는 것이 중요합니다.
repcount는 Logo의 repeat 문에서 자연스럽게 증가하는 값입니다. 이 값이 매우 큰 경우, 특히 내부적으로 사용하는 데이터 타입의 한계를 넘어서면 오버플로우가 발생할 수 있습니다. 그러나 일반적인 Logo 환경에서는 이러한 경우가 드물게 발생합니다.
하지만 무한히 큰 숫자나 매우 큰 반복 횟수를 사용할 때, 시스템의 한계나 구현 방식에 따라 문제가 발생할 수 있습니다. 예를 들어, 32비트 정수형 데이터 타입은 최대 약 21억 (2^31 - 1)까지의 값을 저장할 수 있습니다. 이 범위를 초과하면 오버플로우가 발생하여 부호가 반전될 수 있습니다.
따라서, Logo 프로그램에서 매우 큰 값을 사용할 때에는 이러한 한계를 염두에 두고, 필요한 경우 적절한 범위 내에서 값을 관리하는 것이 좋습니다. 현재 코드에서는 1800번의 반복이므로, 대부분의 환경에서 오버플로우 문제가 발생하지 않을 것입니다.
..."
... 는 불가능합니다만.
그럼 뭔가요...??
5. 응용 연습 1
LT에 사용된 회전각 값만 약간 조정합니다. 도형이 변형되어 텍스트 위치값도 적절하게 조정해줍니다.
to box1 :side
repeat 4 [ fd :side rt 90 ]
end
to boxes
repeat 1800 [
box1 :side pu rt 90 fd :side+5 lt 90
make "A repCount + 0.75
lt :A pd
; show [ repCount : ] Show repCount
; 테스트 용으로 사용
; show [ :A ] show :A
; show 명령은 제법 delay가 발생함.
]
end
to displayText
rt 90
gotoCenter
text1
gotoNextLine
text2
end
to draw
; SLOWDRAW 0
; for Slow Drawing
; FullScreen
; FullScreen, fs <--> SPLITSCREEN, ss
boxes
displayText
HT
end
to gotoCenter
pu lt 90 fd 230 rt 90 back 150 pd
end
to gotoNextLine
pu back 30 pd
end
to main
setup
draw
end
to setup
Window Home CS PPT PD ST
pu rt 90 fd 200 lt 90 back 150 pd
make "side 15
make "A 0
end
to text1
rt 90
label [ "YS is BABO! ^.^ ..." ]
lt 90
end
to text2
rt 90
label [ "SH is BABO too! ^.^ ..." ]
lt 90
end
■ Result ..
6. 응용연습 - 2
거의 달라지지 않았습니다만. 6각형스러운 도형을 그립니다.
to box1 :side
repeat 4 [ fd :side rt 90 ]
end
to boxes
repeat 2160 [
box1 :side pu rt 90 fd :side+5 lt 90
make "A repCount + 0.6669
lt :A pd
; show [ repCount : ] Show repCount
; 테스트 용으로 사용
; show [ :A ] show :A
; show 명령은 제법 delay가 발생함.
]
end
to displayText
; rt 90
gotoCenter
text1
gotoNextLine
text2
end
to draw
; SLOWDRAW 0
; for Slow Drawing
; FullScreen
; FullScreen, fs <--> SPLITSCREEN, ss
setup
boxes
displayText
HT
end
to gotoCenter
pu lt 90 fd 250 rt 90 fd 160 pd
end
to gotoNextLine
pu back 30 pd
end
to main
draw
end
to setup
Window Home CS PPT PD ST
pu rt 90 fd 200 lt 90 back 100 pd
make "side 6
make "A 0
end
to text1
rt 90
label [ "YS is BABO! ^.^ ..." ]
lt 90
end
to text2
rt 90
label [ "SH is BABO too! ^.^ ..." ]
lt 90
end
■ Result ..
우하단, 끝 연결 마감 부분은 대략 어림짐작값으로 처리했습니다. ㅡ.ㅡ;
7. 응용 연습 - 3
LT 값이 180 이상이라면 RT 값으로 전환해서 생각할 수도 있습니다. 예를 들어 LT 181 --> RT 179.
repCount 값을 받아서 사용하고 있는 LT 값이 180(도) 이상이면 RT 값으로 전환해서 그립니다.
180 그 이하일 때는 아예 무시하고 LT 값 적용 부분을 아예 패스해서 LT 값이 적용되지 않으니 직선 형태로 그려집니다.
RT :A에서 변수 A의 값은 180에서 시작해서 1씩 감소하는 방향으로 진행됩니다.
180(도)를 기준으로 그 이하이면 박스를 그리고 그 이상이면 삼각형을 그립니다. 시각적 분리.
박스 크기 때문에 한참 왼쪽에서 시작해야 해서 시작 위치를 무려 3000이나 왼쪽으로 옮겨놓고 시작합니다.
■ Code
to box1 :side
repeat 4 [ fd :side rt 90 ]
end
to boxes
; LT 값이 180 이상이라면 RT 값으로 전환해서 생각할 수도 있습니다.
; 예를 들어 LT 181 --> RT 179.
repeat 360 [
make "A repCount + 0.7
ifelse repCount >= 180 [ ; ifelse의 if 블록
tri1 :side move1
make "mod modulo repCount 180 ; 나머지 구하기.
make "downto :mod * -1 ; 나머지를 음수값으로.
make "A 180 + :downto ; 180부터 시작해서 감소함.
type [ repCount_: ] show repCount ; check. show 명령은 제법 delay가 발생함.
type [ A : ] show :A ; check . type은 비슷한 용도의 print와는 달리 줄을 바꾸지 않는다.
rt :A
; wait 1 ; wait num.에서 num.은 60분의 1초를 의미합니다. 아마도. ^.^;
][
box1 :side move1 ; ifesle의 else 블록
; lt :A
]
]
end
to draw
; SLOWDRAW 0
; for Slow Drawing
; FullScreen
; FullScreen, fs <--> SPLITSCREEN, ss
setup
boxes
printText
HT
end
to gotoNextLine
pu back 30 pd
end
to gotoTextPosition
pu fd 450 rt 90 fd 220 pd
; 도형 그리기의 끝 장면에서 거북이의 위치와 방향과 관계됨.
; pu home pd으로 새로 재조정할 수도 있음.
end
to main
draw
end
to move1
pu rt 90 fd :side+2 lt 90 pd
end
to printText
gotoTextPosition
text1
gotoNextLine
text2
end
to setup
Window Home CS PPT PD ST
pu lt 90 fd 3000 rt 90 back 100 pd
make "side 15
make "A 0
end
to text1
rt 90
label [ "YS is BABO! ^.^ ..." ]
lt 90
end
to text2
rt 90
label [ "SH is BABO too! ^.^ ..." ]
lt 90
end
to tri1 :side
pd repeat 3 [ fd :side rt 120 ] pd
end
■ Result :
■ Comments :
LT 180 이상에서 연속된 LT Curve가 RT Curve처럼 보임. 이 현상에 착안, 응용해서 아예 RT로 명시적으로 그림.
다음 코드는 한 두 줄로 묶어 좀 더 간결하게 표현할 수도 있겠으나 괄호를 사용했더니, ifelse 블록내 괄호가 너무 많다고 뭐라 뭐라 잔소리를 해대서 일단 분리 처리했습니다. ^.^;
make "mod modulo repCount 180 ; 나머지 구하기.
make "downto :mod * -1 ; 나머지를 음수값으로.
make "A 180 + :downto ; 180부터 시작해서 1씩 감소함.
8. Files
9. Ref.
1) FMSLogo 내장 공식 도움말
2) JD8, Comments.
Happy Programming!
^.^;
'Programming > LOGO' 카테고리의 다른 글
LOGO : 변수(Variables) - 018 - 별이 흐르는 밤과 음악 연습 - 1 (0) | 2024.09.08 |
---|---|
LOGO : 변수(Variables) - 017 - 정오각형(Pentagon) 연습 - 2 (0) | 2024.08.18 |
LOGO : 변수(Variables) - 016 - 정오각형(Pentagon) 연습 - 1 (0) | 2024.07.28 |
LOGO : 변수(Variables) - 015 - KFlag (0) | 2024.06.25 |
LOGO : 변수(Variables) - 014 - LevelMeterBox (0) | 2024.06.16 |