Главная страница

Программирование в Scilab Микаэль Боден Micha


Скачать 1.35 Mb.
НазваниеПрограммирование в Scilab Микаэль Боден Micha
Дата18.09.2022
Размер1.35 Mb.
Формат файлаpdf
Имя файлаprogscilab-v.0.10_ru.pdf
ТипРеферат
#683094
страница9 из 13
1   ...   5   6   7   8   9   10   11   12   13

63
значения этих входных переменных по умолчанию. Например, мы можем захотеть исполь- зовать значение по умолчанию order=2, поскольку оно даёт более точные значения произ- водной с тем же количеством выходных значений функции. Задавая порядок, оптимальный шаг h может быть вычислен с помощью одной из оптимальных формул.
Теперь, когда мы знаем какие проблемы встречаются с нашей myderivative1, мы про- анализируем реализацию, основанную на переменном количестве входных и выходных пе- ременных.
4.2.3
Использование переменных аргументов на практике
Целью этого раздела заключается в том, чтобы предоставить реализацию функции,
которая позволяет использовать следующие вызывающие последовательности.
fp = m y d e r i v a t i v e 2 ( m y f u n , x0 )
fp = m y d e r i v a t i v e 2 ( m y f u n , x0 , o r d e r )
fp = m y d e r i v a t i v e 2 ( m y f u n , x0 , o r d e r , h )
[ fp , fpp ] = m y d e r i v a t i v e 2 ( ... )
Главным преимуществом этой реализации являются
• возможно задать значения по умолчанию для order и h,
• вычислять fpp только если она задана пользователем,
• использовать оптимальный шаг h как для первой, так и для второй производной, если это не указано пользователем.
Следующая функция myderivative2 содержит алгоритм конечной разности с опти- мальным порядком myderivative2 и шагом h.
1
\ l s t s e t { l a n g u a g e = s c i l a b s c r i p t }
2
\ l s t s e t { n u m b e r s = l e f t }
3
\ b e g i n { l s t l i s t i n g }
4
f u n c t i o n v a r a r g o u t = m y d e r i v a t i v e 2 ( v a r a r g i n )
5
[ lhs , rhs ]= a r g n ()
6
if ( rhs < 2 | rhs > 4 ) t h e n
7
e r r o r ( m s p r i n t f (..
8
" %s : Ожидалось от %d до %d входных аргументов, но указано
%d " ,..
9
" m y d e r i v a t i v e 2 " ,2 ,4 , rhs ))
10
end
11
if ( lhs > 2 ) t h e n
12
e r r o r ( m s p r i n t f (..
13
" %s : Ожидалось от %d до %d выходных аргументов, но указано
%d " ,..
14
" m y d e r i v a t i v e 2 " ,0 ,2 , lhs ))
15
end
16
f = v a r a r g i n (1)
17
x = v a r a r g i n (2)
18
if ( rhs >= 3 ) t h e n
19
o r d e r = v a r a r g i n (3)
20
e l s e
21
o r d e r = 2 22
end
23
if ( rhs >= 4 ) t h e n
24
h = v a r a r g i n (4)
25
h f l a g = %t
26
e l s e
64

27
h f l a g = %f
28
end
29
if ( o r d e r == 1 ) t he n
30
if (

h f l a g ) t h e n
31
h = % e p s ^ ( 1 / 2 )
32
end
33
fp = ( f ( x + h ) - f ( x ))/ h
34
e l s e
35
if ( h f l a g ) t h e n
36
h = % e p s ^ ( 1 / 3 )
37
end
38
fp = ( f ( x + h ) - f ( x - h ) ) / ( 2 * h )
39
end
40
v a r a r g o u t (1) = fp
41
if ( lhs >= 2 )
th e n
42
if ( o r d e r == 1 ) t he n
43
if ( h f l a g ) t h e n
44
h = % e p s ^ ( 1 / 3 )
45
end
46
fpp = ( f ( x +2* h ) - 2* f ( x + h ) + f ( x ) )/( h ^2)
47
e l s e
48
if ( h f l a g ) t h e n
49
h = % e p s ^ ( 1 / 4 )
50
end
51
fpp = ( f ( x + h ) - 2* f ( x ) + f ( x - h ) )/( h ^2)
52
end
53
v a r a r g o u t (2) = fpp
54
end
55
e n d f u n c t i o n
Поскольку тело этой функции довольно сложное, то мы сейчас проанализируем его основные части.
Строчка №1 определяет функцию, как берущую переменную varargin в качестве вход- ного аргумента, и переменную varargout в качестве выходного аргумента.
Строчка №2 использует функцию argn, которая возвращает настоящее число входных и выходных аргументов. Например, когда используется вызывающая последовательность fp
= myderivative2 ( myfun , x0 ), то мы имеем rhs=2 и lhs=1. Следующий пример пред- ставляет различные возможные вызывающие последовательности.
m y d e r i v a t i v e 2 ( m y f u n , x0 )
// lhs =1 , rhs =2
fp = m y d e r i v a t i v e 2 ( m y f u n , x0 )
// lhs =1 , rhs =2
fp = m y d e r i v a t i v e 2 ( m y f u n , x0 , o r d e r )
// lhs =1 , rhs =3
fp = m y d e r i v a t i v e 2 ( m y f u n , x0 , o r d e r , h ) // lhs =1 , rhs =4
[ fp , fpp ] = m y d e r i v a t i v e 1 ( m y f u n , x0 )
// lhs =2 , rhs =2
Строчки с №2 по №12 добавлены для проверки того, что число входных и выходных ар- гументов правильное. Следующий пример покажет ошибку, которая формируется в случае,
когда пользователь ошибочно вызовет функцию с 1 входным аргументом
- - > fp = m y d e r i v a t i v e 2 ( m y f u n )
! - - e r r o r 1 0 0 0 0
m y d e r i v a t i v e 2 : Ожидалось от 2 до 4 входных аргументов, но указано 1
at l i n e
6 of f u n c t i o n m y d e r i v a t i v e 2 c a l l e d by :
fp = m y d e r i v a t i v e 2 ( m y f u n )
Строчки №13 и №14 показывают как напрямую установить значения входных аргумен- тов f и x, которые всегда должны быть в вызывающей последовательности. Строчки с №15 65
по №19 позволяют установить значения параметра order. Когда число входных аргументов rhs более 3, то мы делаем вывод, что значение переменной order задано пользователем, и мы используем это значение напрямую. В противном случае, мы устанавливаем значение этого параметра по умолчанию, то есть мы устанавливаем order=2.
Тот же самый процесс проведён в строчках с №20 по №25 для того, чтобы устано- вить значение h. Более того, мы устанавливаем значение логической переменной hflag. Эта переменная устанавливается равной %t, если пользователь указал h и в %f, если нет.
Строчки с №26 по №36 позволяют вычислить первую производную, а вторые производ- ные вычисляются в строчках с №38 по №51. В каждом случае, если пользователь не укажет h, то есть, если hflag установлен в «ложь», то используется оптимальный шаг.
Число выходных переменных должно быть больше или равно одному. Следовательно,
не нужно проверять значение lhs перед установкой varargout(1) в строчке №37.
Один важный момент заключается в том, что вторая производная fpp вычисляет- ся только если это потребуется пользователю. Это гарантируется в строчке №38, которая проверяет количество выходных переменных: вторая производная вычисляется только если второй выходной аргумент fpp был действительно записан в вызывающей последователь- ности.
Следующий пример показывает простое использование функции myderivative2, где мы использовали значение по умолчанию как для order, так и h.
- - > f o r m a t ( " e " ,25)
- - > x0 = %pi /6;
- - > fp = m y d e r i v a t i v e 2 ( m y f u n , x0 )
fp
=
- 5 . 0 0 0 0 0 0 0 0 0 0 2 6 0 9 4 6 8 2 D -01
Заметим, что в этом случае вторая производная не вычислялась, что может сохранить зна- чительное количество времени.
В следующем примере мы установили значение order и использовали значение по умол- чанию h.
- - > fp = m y d e r i v a t i v e 2 ( m y f u n , x0 , 1 )
fp
=
- 5 . 0 0 0 0 0 0 0 7 4 5 0 5 8 0 5 9 6 9 D -01
Мы можем также вызвать эту функцию с двумя выходными аргументами, как в сле- дующем примере.
- - >[ fp , fpp ] = m y d e r i v a t i v e 2 ( m y f u n , x0 , o r d e r )
fpp
=
- 8 . 6 6 0 2 5 4 0 3 1 4 1 9 7 5 4 0 2 8 D -01
fp
=
- 5 . 0 0 0 0 0 0 0 0 0 0 2 6 0 9 4 6 8 2 D -01
Заметим, что в этом случае оптимальный шаг h использовался как для первой, так и для второй производной.
В этом разделе мы видели как управлять числом переменных входных и выходных аргументов.
Но, в некоторых ситуациях, этого не достаточно и по-прежнему имеются ограниче- ния. Например, метод, который мы представили ограничен порядком аргументов, то есть,
их положением в вызывающей последовательности. В самом деле, функция myderivative2
не может быть вызвана использованием значений по умолчанию для аргументов order и установкой настраиваемых значений для аргумента h. Это ограничение вызвано порядком
66
аргументов: входной аргумент h идёт после аргумента order. На практике удобно, если мож- но использовать значение по умолчанию для аргумента №i, и по-прежнему устанавливать значение аргумента №i + 1 (или любого другого аргумента в правой части вызывающей последовательности). Следующий раздел позволяет решить этот вопрос.
4.2.4
Значения по умолчанию для необязательных аргументов
В этом разделе мы опишем как управлять необязательными аргументами со значе- ниями по умолчанию. Мы покажем как решить проблему, порождённую упорядоченными входными переменными с помощью специального использования синтаксиса пустых матриц
[].
Действительно, мы видели в прошлом параграфе, что основное управление необяза- тельными аргументами запрещает нам устанавливать входной аргумент №i + 1 и использо- вать значение по умолчанию для входного аргумента №i. В этом разделе мы покажем метод,
где пустая матрица используется для представления параметра по умолчанию.
Давайте рассмотрим функцию myfun, которая принимает x, p и q в качестве входных переменных и возвращает выходной аргумент y.
f u n c t i o n y = m y f u n ( x , p , q )
y = q * x ^ p e n d f u n c t i o n
Если мы установим все x, p и q в качестве входных аргументов, то функция работает превосходно, как в следующем примере.
- - > m y f u n (3 ,2 ,1)
ans
=
9.
Сейчас наша функция myfun не очень гибкая, так что, если мы передадим только один или два аргумента, то функция вызовет ошибку.
- - > m y f u n (3)
! - - e r r o r 4
Неизвестная переменная: q at l i n e
2 of f u n c t i o n m y f u n c a l l e d by :
m y f u n (3)
- > m y f u n (3 ,2)
! - - e r r o r 4
Неизвестная переменная: q at l i n e
2 of f u n c t i o n m y f u n c a l l e d by :
m y f u n (3 ,2)
Было бы удобно, если бы, например, параметр p имел по умолчанию значение 2, а параметр p имел по умолчанию значение 1. В этом случае, если ни p ни q не указаны, то команда foo(3) должна вернуть 9.
Мы можем использовать переменную varargin для того, чтобы иметь переменное чис- ло входных переменных. Но, используя напрямую, это не позволит установить третий аргу- мент и использовать значение по умолчанию для второго аргумента. Эта проблема вызвана упорядочиванием входных переменных. Для того, чтобы решить эту проблему, мы будем по-особенному использовать пустую матрицу [].
67

Преимущество этого метода заключается в возможности использовать значение по умолчанию аргумента p, при этом устанавливать значение аргумента q. Для того, чтобы информировать функцию, что особый аргумент должен быть установлен равным значению по умолчанию, мы устанавливаем его равным пустой матрицу. Эта ситуация представлена в следующем примере, где мы устанавливаем аргумент p равным пустой матрице.
- - > m y f u n 2 (2 ,[] ,3) // то же, что и m y f u n 2 (2 ,2 ,3)
ans
=
12.
Для того, чтобы определить функцию, мы используем следующий метод. Если входной аргумент не указан, или если он указан равным пустой матрице, то мы используем значение по умолчанию. Если аргумент указан и отличается от пустой матрицы, то мы используем непосредственно его. Этот метод представлен в функции myfun2.
1
f u n c t i o n y = m y f u n 2 ( v a r a r g i n )
2
[ lhs , rhs ]= a r g n ()
3
if ( rhs <1 | rhs >3 ) t h e n
4
msg = g e t t e x t ( " %s : W r o n g n u m b e r of i n p u t a r g u m e n t s : %d to %d e x p e c t e d .\ n " )
5
e r r o r ( m s p r i n t f ( msg , " m y f u n 2 " ,1 ,3))
6
end
7
x = v a r a r g i n (1)
8
p d e f a u l t = 2 9
if ( rhs >= 2 ) t h e n
10
if ( v a r a r g i n (2) < > [] ) t h e n
11
p = v a r a r g i n (2)
12
e l s e
13
p = p d e f a u l t
14
end
15
e l s e
16
p = p d e f a u l t
17
end
18
q d e f a u l t = 1 19
if ( rhs >= 3 ) t h e n
20
if ( v a r a r g i n (3) < > [] ) t h e n
21
q = v a r a r g i n (3)
22
e l s e
23
q = q d e f a u l t
24
end
25
e l s e
26
q = q d e f a u l t
27
end
28
y = q * x ^ p
29
e n d f u n c t i o n
С точки зрения алгоритма мы могли бы выбрать другое опорное значение, отличное от пустой матрицы. Например, мы могли бы рассматривать пустую строку или любое другое особое значение. Причина, почему пустая матрица предпочитается на практике состоит в том, что сравнение с пустой матрице быстрее, чем сравнение с любым другим особым зна- чением. Действительное содержимое матрицы не имеет значения, поскольку сравнивается только размер матрицы. Следовательно, накладные расходы на производительность из-за управления значениями по умолчанию малы как только можно.
Конечно, мы по-прежнему можем использовать необязательные аргументы как обычно,
как это показано ниже.
- - > m y f u n 2 (2)
68
ans
=
4.
- - > m y f u n 2 (2 ,3)
ans
=
8.
- - > m y f u n 2 (2 ,3 ,2)
ans
=
16.
На практике этот метод и гибок и надёжен, с основным управлением входных пере- менных, которые по-прежнему главным образом зависят от их порядка.
Этот метод по-прежнему ограничен, если число входных переменных велико. В этом случае существуют другие решения, которые позволяют использовать упорядоченные аргу- менты.
В разделе
4.4
мы анализируем модуль parameters, который позволяет конфигуриро- вать неупорядоченный набор входных аргументов отдельно из действительного использова- ния параметров. Другое решение заключается в том, чтобы имитировать объектно-ориен- тированное программирование, как показано в разделе
3.7 4.2.5
Функции с переменным типом входных аргументов
В этом разделе мы представляем функцию, чьё поведение зависит от типа её входных аргументов.
Следующая функция myprint указывает особое отображение для матрицы значений типа double и другое отображение для матрицы логических значений. Тело функции осно- вано на команде if, которая переключает различные части исходного кода в зависимости от типа переменной X.
f u n c t i o n m y p r i n t ( X )
if ( t y pe ( X ) == 1 ) th e n d i s p ( "Матрица значений типа double" )
e l s e i f ( t y p e ( X ) == 4 ) t h e n d i s p ( "Матрица логических значений" )
e l s e e r r o r ( "Неожиданный тип. " )
end e n d f u n c t i o n
В следующем примере мы вызываем функцию myprint с двумя разными типами мат- риц.
- - > m y p r i n t ( [1 2] )
Матрица значений типа double
- - > m y p r i n t ( [ %T %T ] )
Матрица логических значений
Мы можем сделать предыдущую функцию более полезной, определив отдельно прави- ла форматирования для каждого типа данных. В следующей функции мы группируем три значения, отделённых большим пропуском, который визуально создаёт группы переменных.
f u n c t i o n m y p r i n t ( X )
if ( t y pe ( X ) == 1 ) th e n
// Вещественная или комплексная матрица for i = 1 : s i z e ( X , " r " )
for j = 1 : s i z e ( X , " c " )
m p r i n t f ( " % -5 d " , X ( i , j ))
69
if ( j == 3 ) t h e n m p r i n t f ( "
" )
end end m p r i n t f ( " \ n " )
end e l s e i f ( t y p e ( X ) == 4 ) t h e n
// Матрица логических значений for i = 1 : s i z e ( X , " r " )
for j = 1 : s i z e ( X , " c " )
m p r i n t f ( " %s " , s t r i n g ( X ( i , j )))
if ( j == 3 ) t h e n m p r i n t f ( "
" )
end end m p r i n t f ( " \ n " )
end e l s e e r r o r ( "Неожиданный тип входного аргумента" )
end e n d f u n c t i o n
Следующий пример показывает использование предыдущей функции. Сначала отоб- разим матрицу значений типа double.
- - > X = [
- - >1 2 3 4 5 6
- - >7 8 9 10 11 12
- - >13 14 15 16 17 18
- - >];
- - > m y p r i n t ( X )
1 2
3 4
5 6
7 8
9 10 11 12 13 14 15 16 17 18
Затем отобразим матрицу логических значений.
- - > X = [
- - > %T %T %F %F %F %F
- - > %T %F %F %T %T %T
- - > %F %T %F %F %T %F
- - >];
- - > m y p r i n t ( X )
T T F
F F F
T F F
T T T
F T F
F T F
Многие встроенные функции разработаны на этом принципе. Например, функция roots возвращает корни многочлена. Её входные аргументы могут быть либо многочленом либо матрицей значений типа double, представляющих его коэффициенты. На практике, возмож- ность управлять разными типами переменных в одной функции даёт дополнительный уро- вень гибкости, который гораздо сложнее получить в компилируемых языках, таких как Си или Фортран.
70

4.3
Устойчивые функции
В этом разделе мы представляем некоторые правила, которые можно применять ко всем функциям которые разрабатываются так, чтобы быть устойчивыми при неправильном использовании. В следующем разделе мы представим функции warning и error, которые являются основой разработки устойчивых функций. Затем мы представим общую схему работы для проверок, используемых внутри устойчивых функций. Наконец мы представим функцию, которая вычисляем матрицу Паскаля и покажем как применять эти правила на практике.
4.3.1
Функции warning и error
Часто случается, что входные аргументы функции могут иметь только ограниченное число возможных значений. Например, мы могли бы потребовать, чтобы данное входное число было положительным, или что данное число с плавающей запятой могло иметь толь- ко три возможных значения. В этом случае мы можем использовать функции error или warning, которые представлены на рисунке
23
. Функция gettext относится к локализации и описана позднее в этом разделе.
error
Посылает сообщение об ошибке и останавливает вычисление.
warning
Посылает сообщение-предупреждение.
gettext
Получает текст, переведённый на местный язык.
Рис. 23: Функции, относящиеся к сообщениям об ошибке.
Теперь дадим пример, который показывает как эти функции могут использоваться для защиты пользователя функции от неправильного использования. В следующем примере мы определяем функцию mynorm, которая является упрощённой версией встроенной функции norm. Наша функция mynorm позволяет вычислить 1-, 2- или ∞-норму вектора. В противном случае наша функция не определена и поэтому формируется ошибка.
f u n c t i o n y = m y n o r m ( A , n )
if ( n == 1 ) t h e n y = sum ( abs ( A ))
e l s e i f ( n == 2 ) t h e n y = sum ( A . ^ 2 ) ^ ( 1 / 2 ) ;
e l s e i f ( n == " inf " ) t h e n y = max ( abs ( A ))
e l s e msg = m s p r i n t f ( " %s : I n v a l i d v a l u e %d for n . " , " m y n o r m " , n )
1   ...   5   6   7   8   9   10   11   12   13


написать администратору сайта