1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
*(Вопрос) У меня есть макрос, который включает цикл !DO - !DOEND. Его цель - 
	повторять итерации до тех пор, пока не будет достигнута точность
	по заранее установленному критерию. Каждая итерация занимает достаточно
	много времени. Как остановить процесс, когда критерий будет достигнут?

* (Ответ) Автор: Raynald Levesque, 22.09.2001
	Чтобы проиллюстрировать решение, я сначала привожу макрос, который
	не останавливается, когда критерий выполнен. Затем я модифицирую его так, 
	чтобы он останавливался. (На самом деле, цикл продолжает выполняться, но без	выполнения каких-либо команд внутри него). 
	
* Имя файла: MacroExitsLoopWhenDataMeetConvergenceCriteria.SPS.

SET SEED=12365981.
SET MPRINT=yes.

*/////////////////////////////////.
DEFINE !eloop1 (max=!TOKENS(1))

!DO !cnt=1 !TO !max
COMPUTE cnt=!cnt.

* Следующий цикл DO IF - END IF  - просто шаблон для реальных вычислений.
* Предположим, что если у нас conver=1, критерий сходимости достигнут.
DO IF $CASENUM=1.
COMPUTE conver=TRUNC(UNIFORM(10)).
ELSE.
COMPUTE conver=LAG(conver).
END IF.
LIST.
!DOEND

!ENDDEFINE.
*/////////////////////////////////.

!eloop1 max=10. /* Этот макрос продолжает выполняться даже если conver=1*/.

exe.

***********************************************************************.
*
*	Со следующими модификациями
*	 макрос прекращает выполнение действий как только
*	критерий сходимости достигнут.
*
***********************************************************************.

SET SEED=12365981.
/* Поскольку выше использован сброс генератора случайных чисел, и в данном примере */
/* генератор используется лишь для имитации сходимости на первом наблюдении, данный */
/* пример всегда сходится на 7 итерации. Номер последней итерации, на которой */
/* проводились вычисления, печатается в окно результатов командой PRINT. - А.Б. */
SET MPRINT=no.
DEFINE !ok()0!ENDDEFINE.

DEFINE !eloop2 (max=!TOKENS(1))

!DO !cnt=1 !TO !max
COMPUTE cnt=!cnt.

DO IF !ok<>1.
+	DO IF $CASENUM=1.
+	COMPUTE conver=TRUNC(UNIFORM(10)).
+	ELSE.
+	COMPUTE conver=LAG(conver).
+	END IF.
+	DO IF $CASENUM=1.
+	FORMAT conver (F2.0).
+	WRITE OUTFILE='c:\\temp\\temp.SPS' /"DEFINE !ok()" conver "!ENDDEFINE.".
+	END IF.
+	PRINT /cnt 1-2 conver 3-4.
END IF.
EXECUTE.
INCLUDE FILE='c:\\temp\\temp.SPS' .
!DOEND
!ENDDEFINE.


!eloop2 max=10. /* Этот макрос останавливается когда conver=1*/.

exe.