답변:
조건을 확인하고 싶다고 가정 해 보자 a==b
( 각각 명명 된 레지스터에 저장 a
및 b
저장).
[ # Everything is wrapped in one big macro
[ # An inner macro for our *then* part
# <-- Stuff to execute if a==b here
2Q # Then quit the inner and outer macro
]sE # `E' is for Execution register ;)
la lb =E # if a==b, execute E
# if E is executed, it will quit the whole macro, so the rest is never reached:
# <-- Stuff to execute if a!=b here
]x # End macro; Execute
하자 (foo)
응축의 목적에 대한 자리가 될 :
[[(then)2Q]sE(condition)E(else)]x
이것이 가능한 가장 컴팩트 한 if 문인지 확인하십시오 ( 여기에도 나와 있습니다 ).
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI f
시작일까요? tehn 및 기타 조치는 스택에 있으며 " I
f"매크로는이를 교환하고 조건부로 계산됩니다. 그런 다음 스택 맨을 실행하고 사용하지 않는 매크로를 삭제하여 스택을 정리합니다. 2 4
비교할 예제 데이터 일뿐입니다. 대안 [x]sI
가독성을 고려하면 부분은, 비교로 이동 할 수 있습니다 [[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f
. f
스택 나중에 깨끗 TAT 예에서 그냥 .. 제시해야한다
dc
했으며 이것이 OpenBSD dc
의 if-then-else
구조를 본 첫 페이지였습니다 . dc
모든 주요 운영 체제에 대해 3 가지 맛을 모두 갖춘 팬 번들이 필요하다고 생각 합니다 ... o :-) ... if-then-else
위의 제안 dc
은 r
명령 이 없기 때문에 원본에서 작동하지 않습니다 ... :-(
[[(if)2Q]si(condition)i(else)]x
- 당신이 할 수 그래서, 매크로에서 전체를 포장하고, 그 안에 다른 매크로 내부의 경우-부분 2Q
else 블록 부분에 도달하기 전에 모든 일에서 당신의 방법을 UIT. 당신이 원하는 경우에 따라서 경우 1 == 1 다음 한 다른 인쇄 (2) 인쇄 , 그것은 것 1[[1P2Q]si1=i2P]x
내가 바로 여기 그리고 지금 직류에 액세스 할 수 없습니다로 (검증되지 않은. 또한 반드시 내가 여기 전에 대답이 트릭을 수행 있었다 하지만 찾을 수 없습니다)
[/*else*/]sE[[/*then*/]sE]sIlalb=IlEx
대 [[/*then*/2Q]sIlalb=I/*else*/]x
6의 차이를 바이트 -. 아직 검증되지 않은 상점 : P
초보자에게는 골치 거리이지만 dc
배열을 제공합니다. 그들은 다음과 같이 작동합니다 :
value index :a # store `value' in array linked to top of stack `a', with index `index'
index ;a # push a[index] on (main) stack
평소와 같이 첫 번째 요소는 인덱스 0을 갖습니다. 배열은 SUDSI sequence 에서처럼 특히 카운터와 결합하여 시퀀스로 작업 할 때 유용 할 수 있습니다 . 배열은 환경을 파괴하지 않고 특정 요소를 선택하려는 경우 수행해야하는 수 셔플 링 양 (및 카운터 및 비교 수)을 줄일 수 있습니다. 예를 들어, 많은 수의 배열을 배열로 이동하려면 z
(스택 깊이)를 사용하거나 z 1-
인덱스로 요소를 저장하고 z == 0
자체 종료 여부 를 확인 하는 재귀 함수를 작성할 수 있습니다.
[z 1- :a z 0 !=F]dsFx # or I could just write such a function for you :)
다음 사항에 유의하십시오.
dc
충돌합니다.dc
최근에 업데이트되었을 수 있으며 충돌과 관련하여 배열 동작이 약간 변경되었을 수 있습니다. 지금도 확인할 수는 없지만 Linux에서 마지막으로 사용했을 때 뭔가 다른 것으로 생각합니다.
때때로 당신은 뭔가해야 할 수도 있습니다 C 삼항 조건을 :
A == B ? C : D;
이를 처리하는 좋은 방법은 @ Joe 's answer에 설명되어 있습니다. 그러나 우리는 더 잘할 수 있습니다.
0AB-^E*C+
여기서 E는 D-C입니다.
이것은 두 값의 차이의 거듭 제곱으로 0을 올림으로써 동등성을 테스트합니다. 같으면 1, 그렇지 않으면 0이됩니다. 나머지는 1 또는 0을 값 C 또는 D로 스케일링합니다. 이것은 n! = 1에 대해 dc
0 0 = 1 및 0 n = 0을 주기 때문에 작동 합니다 .
때때로 스택에서 숫자를 폐기해야합니다. 이를 수행하는 한 가지 방법은 변수를 사용하지 않는 변수, 즉 st
. 그러나 어떤 상황에서는 더 이상 숫자 입력이 없을 때 입력 기준 또는 정밀도가 다른 곳에서 수행 할 작업이 더 이상없는 경우 정밀도 지정자에 두 개의 다른 위치에이를 표시 할 수 있습니다. 전자의 경우을 사용하십시오 i
. 후자의 경우을 사용하십시오 k
.
o
에도 사용할 수 있습니다. 이러한 것들 중 하나가 중요하지 않은 경우, 그들은 스토리지뿐만 아니라 단순한 폐기로 사용할 수 있습니다 - I
/ K
/이 O
각각 그들을 기억, 이상 바이트 저장 sa
/ la
등 유효한 값 AFAIK을 : i
2-16; k
음이 아닌 정수; o
1보다 큰 정수
Z
, X
, 및z
Z
ToS를 팝하고 숫자 인 경우 자릿수 (10 진수) 또는 문자열 인 경우 문자 수를 푸시합니다. 이는 결과 길이 (버퍼링 출력)를 감지하거나 문자열 길이를 계산하는 데 유용 할 수 있습니다. 숫자 Z
의 경우 정수 부분과 분수 부분의 결합 된 길이를 푸시합니다.
X
ToS를 팝하고 숫자의 소수 부분에서 자릿수를 푸시합니다. ToS가 문자열 인 0
경우 푸시됩니다.
숫자의 정수 부분에서 자릿수를 찾으려면을 사용할 수 있습니다 dZrX-
. 기본값에서 정밀도를 변경하지 않은 경우를 k==0
사용하는 1/Z
것이 더 짧지 만 작업 후 0이 아닌 특정 정밀도를 유지해야한다고 가정하십시오 Kr0k1/Zrk
.
z
스택의 항목 수를 푸시합니다. 내가 가장 좋아하는 명령 중 하나이며 실제로 값을 표시하지 않습니다! 일련의 숫자를 생성하거나 카운터를 증가시키는 데 사용될 수 있습니다. zd
매크로를 시작할 때 반복적으로 사용하면 각 자연수 또는 정수에 대한 계산 을 오름차순으로 테스트 할 수 있습니다.
z
이과 그 전에,하지만 카운터의 해킹 ... 우수 ...로 사용하는 나에게 발생하지 않았다
숫자 A
행 F
들이 아직도 여행자 효과적으로 10 개 자리를 처리해야하지만 (15)에 숫자 10을 대신하여 사용될 수있다 (입력 기본 가정은 10이다) 때 다른 장소이다. 즉, 입력 기준이 10 FF
인 경우 255를 나타내지 (15 * 10) + 15
않거나 165를 나타냅니다 .
사실이 모든 숫자 작동 0
으로 F
모든 입력 기지 2
에 16
. 입력 염기가 5이면 그렇다면, 26E
것 (2 * 5^2) + (6 * 5) + 14
, 또는 94.
이 동작은 수정되지 않은 GNU 소스에 적용됩니다. 그러나 @SophiaLechner가 지적했듯이 RedHat 기반 배포판은 bc-1.06-dc_ibase.patch 를 사용 하여이 동작을 변경 ibase - 1
하여 실제 값에 관계없이 숫자> = ibase 가로 취급됩니다 . TIO dc
는 bc-1.06-dc_ibase.patch를 가지고 있지 않습니다 (Fedora 28 ¯_ (ツ) _ / ¯).
FF
는를 나타내고 99
, 입력베이스 (5) 26E
는 244
베이스 (10) 와 동일하다 74
.
dc
버전을 실행하고 있습니까? 우분투에서 GNU dc 1.4.1을 사용하고 MacOS에서 GNU dc 1.3을 사용하고 있습니다
FFp
출력 99
된다는 것입니다. 그렇다면 MacOS 버전에서이를 확인할 수 있습니까?
우연히 이것을 발견했습니다. 0을 생성하는 또 다른 방법 : _
.
_
다음 숫자가 음수라는 dc 신호입니다. 예:
_3 # pushes -3
그러나 우리가 숫자를 따르지 않으면 어떻게 될까요?
_ # pushes 0...sometimes
밑줄 뒤의 다음 비 공백 문자가 숫자가 아닌 경우에 작동합니다. 줄 바꿈 후에도 숫자가 뒤에 오면 음수로 해석됩니다.
c4 5_6 # -6,5,4
c4 5_ 6 # -6,5,4
c4 5_
6 # -6,5,4 # still a negative sign since the next thing it sees is a digit
c4 5_z # 3,0,5,4 # if it's followed by a non-digit, it's a 0
c4 5_p6 # 6,0,5,4
c4 _* # 0 # 4*0=0
dc
한 번에 한 줄씩 입력을 읽습니다. 여러 항목을 읽어야하는 경우 한 줄에 하나씩 수행하려면 ?
모든 줄을 읽거나 번거로운 매크로 루프가 필요합니다. 대신 모든 입력 항목을 공백으로 구분 된 한 줄에 넣을 수 있으면 단일 ?
항목이 모든 입력 항목을 읽고 각 항목을 스택으로 밀어 넣습니다.
예를 들어에서 seq 10 | dc -e'?f'
, seq
라인 당 하나씩 정수 1-10을 출력합니다. 는 전체 스택을 덤프 할 때 출력되는 ?
첫 번째 1
를 읽습니다 f
. 그러나에서 seq 10 | tr '\n' ' ' | dc -e'?f'
상기는 tr
모든 공간이 분리 된 정수 입력한다. 이 경우에는 ?
행에서 모든 정수를 한 번에 읽고 모두 f
출력합니다.
a
몇 번이나 나에게 유용한 것은 이제 연산자의 ASCII 값을 푸시하고 a
문자열로 변환하는 데 사용 하고 s
나중에 매크로로 실행되도록 레지스터에서이 연산자를 사용하여 특정 연산자를 사용하지 않는 것입니다 의 위에. 예를 들어, 나눗셈을해야하지만 캐릭터 사용을 금지하거나 피하려고합니다 /
. 대신 47asd
16을 4로 나누어야 할 때 대신 할 수 있습니다 16 4 ldx
.
s
은 무언가로 접미사가 필요 하지 않습니다 .공백을 피하는 것은 상당히 어려운 문제이며 일반적으로 쉽습니다 dc
. 문자열 외에도 공백이 필요한 매우 구체적인 시간은 여러 개의 숫자를 연속으로 밀어 넣는 경우입니다 1 2 3
. 이것을 피해야하는 경우 :
1[]x2[]x3[]x
.35asn
실행 하십시오1lnx2lnx3lnx
.dc: ',' (054) unimplemented
경고를 할 의향이 있다면 쉼표로 구분 된 숫자를 사용할 수도 있습니다 .