Zurück zum Inhaltsverzeichnis
Kapitel 30
Fehlerbehandlung
tracelast
> restart:
>
test:=proc(a,b)
local n1, n2, i:
n1:=a: n2=b:
seq(i,i=n1..n2);
end:
> test(3,4);
Error, (in test) unable to execute seq
> tracelast;
test called with arguments: 3, 4
#(test,3): seq(i,i = n1 .. n2)
Error, (in test) unable to execute seq
locals defined as: n1 = 3, n2 = n2, i = i
trace
> restart:
>
test:=proc(x)
if x>1 then x*test(x-1)
else 1 fi:
end:
> trace(test);
> test(2);
>
test:=proc(x)
option trace:
if x>1 then x*test(x-1)
else 1 fi:
end:
> test(2);
{--> enter test, args = 2
{--> enter test, args = 1
<-- exit test (now in test) = 1}
<-- exit test (now at top level) = 2}
debugging procedures
> restart;
>
f:=proc(x)
option remember;
if x=0 then 0
elif x=1 then 1
else f(x-1)+f(x-2) fi
end:
> f(2.5);
Error, (in f) too many levels of recursion
> showstat(f);
f := proc(x)
1 if x = 0 then
2 0
elif x = 1 then
3 1
else
4 f(x-1)+f(x-2)
fi
end
> stopat(f,4,x<0);
> f(2.5);
f:
4? f(x-1)+f(x-2)
DBG> x;
-.5
f:
4? f(x-1)+f(x-2)
DBG> where
TopLevel: f(2.5)
[2.5]
f: f(x-1)+f(x-2)
[1.5]
f: f(x-1)+f(x-2)
[.5]
f: f(x-1)+f(x-2)
[-.5]
f:
4? f(x-1)+f(x-2)
DBG> list
f := proc(x)
1 if x = 0 then
2 0
elif x = 1 then
3 1
else
4?! f(x-1)+f(x-2)
fi
end
DBG> quit
Warning, computation interrupted
printlevel, infolevel
>
test:=proc(x)
if x>1 then x*test(x-1)
else 1 fi:
end:
> printlevel:=20:
> test(3);
{--> enter test, args = 3
{--> enter test, args = 2
{--> enter test, args = 1
<-- exit test (now in test) = 1}
<-- exit test (now in test) = 2}
<-- exit test (now at top level) = 6}
> printlevel:=1:
>
>
test:=proc(x)
userinfo(3, `test`, `Hello, Maple!`):
x^2:
end:
> test(3);
> infolevel[test]:=3:
> test(3);
test: Hello, Maple!
traperror
> test:=proc(x) 1/x: end:
> traperror(test(3));
> lasterror;
> traperror(test(0));
> lasterror;
maplemint
>
seqn:= proc( f, l::list )
local i, data, range, `&vgl`;
range:=l:
# type checking
if not type(range[1],name=`..`) then
ERROR(`falscher Parameter`, range);
elif nops(range)>1 then
if not type(range[2], algebraic) or evalf(range[2])=0 then
ERROR(`falscher Parameter`, range);
fi;
else
range:=[ op(range), 1]:
fi;
# data will contain the nested list
data:=[]:
# i is the loop variable
i:=op(1,op(2,range[1])):
# up- or down-loop?
if evalf(range[2])>0 then `&vgl`:=(x,y)->(x<=y):
else `&vgl`:=(x,y)->(x>=y): fi:
# execute outer-loop
while evalf(i) &vgl evalf(op(2,op(2,range[1]))) do
if nargs>2 then
# call seqn recursivly for inner loops
data := [ op(data),
seqn( eval(subs( op(1,range[1])=i, f)),
op(eval(subs( op(1,range[1])=i, [args[3..nargs]])))) ];
else
data := [ op(data), eval(subs( op(1,range[1])=i, f)) ];
fi:
i:=eval(i)+range[2];
od;
[op(data)];
end:
> maplemint(seqn);
These local variables have the same name as system names:
range
These local variables have the same name as constants:
37
These names were used as global names, but were not declared:
`falscher Parameter`
These local variables were assigned a value, but otherwise unused:
`&vgl`
try - catch - finally
Sicheres schreiben in Dateien:
>
speicherePZ:=proc(Dateiname,anzahl)
local datnr,i;
try
datnr:=fopen(Dateiname,WRITE,TEXT);
catch "file I/O error":
error "Datei %1 konnte nicht geöffnet werden!",Dateiname;
end try;
i:=1;
try
while i<=anzahl do
fprintf(datnr,"Die %dte Primzahl ist: %d\n",i,ithprime(i));
i:=i+1;
if i>5 then
error "Zahl zu groß %1",i;
end if;
end do
catch:
printf("Das war ein Fehler: i=%d",i);
error;
finally
fclose(datnr);
end try
end proc:
> speicherePZ("c:\\dat1.txt",20);
Das war ein Fehler: i=6
Error, (in speicherePZ) Zahl zu groß 6
>
>
Analyse des Zeit- und Speicherbedarfs von Prozeduren
showtime
> restart:
> showtime();
O1 := simplify(sin(x)^2+cos(x)^2);
time = 0.34, bytes = 215930
O2 := int(1/(1+x^5),x):
time = 1.67, bytes = 1841878
O3 := O1;
time = 0.01, bytes = 3114
O4 := off;
profile
> restart:
>
nestprint:=proc(x)
local i,n;
if nargs=2 then n:=args[2]; else n:=0; fi:
for i from 0 to n do printf(` `); od:
if type(x,function) then
lprint(op(0,x));
for i from 1 to nops(x) do: nestprint(op(i,x),n+1): od:
elif nops(x)>1 then
lprint(whattype(x));
for i from 1 to nops(x) do: nestprint(op(i,x),n+1): od:
else
lprint(op(x));
fi;
end:
>
> profile(nestprint,lprint,int):
> nestprint( int(1/(1+x^5),x));
`+`
`*`
fraction
1
5
ln
`+`
x
1
`*`
fraction
-1
20
ln
`+`
`*`
2
`^`
x
2
`*`
-1
x
`*`
-1
`^`
5
fraction
1
2
x
2
`*`
fraction
-1
20
ln
`+`
`*`
2
`^`
x
2
`*`
-1
x
`*`
-1
`^`
5
fraction
1
2
x
2
`^`
5
fraction
1
2
`*`
`^`
`+`
10
`*`
-2
`^`
5
fraction
1
2
fraction
-1
2
arctan
`*`
`+`
`*`
4
x
-1
`*`
-1
`^`
5
fraction
1
2
`^`
`+`
10
`*`
-2
`^`
5
fraction
1
2
fraction
-1
2
`*`
fraction
-1
5
`^`
`+`
10
`*`
-2
`^`
5
fraction
1
2
fraction
-1
2
arctan
`*`
`+`
`*`
4
x
-1
`*`
-1
`^`
5
fraction
1
2
`^`
`+`
10
`*`
-2
`^`
5
fraction
1
2
fraction
-1
2
`^`
5
fraction
1
2
`*`
fraction
1
20
ln
`+`
`*`
2
`^`
x
2
`*`
-1
x
`*`
`^`
5
fraction
1
2
x
2
`^`
5
fraction
1
2
`*`
fraction
-1
20
ln
`+`
`*`
2
`^`
x
2
`*`
-1
x
`*`
`^`
5
fraction
1
2
x
2
`*`
`^`
`+`
10
`*`
2
`^`
5
fraction
1
2
fraction
-1
2
arctan
`*`
`+`
`*`
4
x
-1
`^`
5
fraction
1
2
`^`
`+`
10
`*`
2
`^`
5
fraction
1
2
fraction
-1
2
`*`
fraction
1
5
`^`
`+`
10
`*`
2
`^`
5
fraction
1
2
fraction
-1
2
arctan
`*`
`+`
`*`
4
x
-1
`^`
5
fraction
1
2
`^`
`+`
10
`*`
2
`^`
5
fraction
1
2
fraction
-1
2
`^`
5
fraction
1
2
> showprofile();
function depth calls time time% bytes bytes%
---------------------------------------------------------------------------
int 1 1 .200 55.40 1854316 64.82
nestprint 10 285 .101 27.98 931784 32.57
lprint 1 285 .060 16.62 74528 2.61
---------------------------------------------------------------------------
total: 12 571 .361 100.00 2860628 100.00
> unprofile(nestprint,lprint,int):
Die neue Funktion seqn
> restart:
Version 1: seq1
>
seq1:= proc( f::uneval, range::uneval )
local i, data,von,bis,inc, `&vgl`, seqvar;
if not type(range,name=`..`) then
error "Das zweite Argument soll die Form name=Bereich haben %0",range;
end if;
von:= eval(lhs(rhs(range)));
bis:= eval(rhs(rhs(range)));
seqvar:= lhs(range);
if (nargs>2) then
inc:=args[3];
elif is(von >= bis) then
inc:=-1;
else inc:=1;
end if;
if is(inc=0) then
error "Das Schleifeninkrement darf nicht 0 sein";
end if:
if not (type(eval(inc),algebraic)) then
error "Das Inkrement muss algebraisch sein";
end if;
if (is(von <= bis) and is(inc>0)) or (is(von>=bis) and is(inc>0)) then
`&vgl`:=(x,y)->is(x <= y);
else
`&vgl`:= (x,y)->is(x >= y);
end if;
data:=NULL:
i:=von;
while is(i &vgl bis) do
data := data, eval(subs( seqvar=i, f));
i:=i+inc;
end do;
data;
end:
>
>
> seq1(x^2, x=6..2, -0.5);
> seq1(x^2, x=0..Pi, Pi/4);
>
x:=3:seq1(x^2, x=2..3,1);
> x:='x':
> seq1(sin(n*x),x=0..2*Pi, Pi/2);
>
n:=1/8:
seq1(sin(n*x),x=0..2*Pi, Pi/2);
> n:='n':
> seq1([seq1(x*y,x=0..3,1/2)],y=1..2);
> [seq1([seq1(x*y,y=2..4)],x=0..6,2)];
Version 2: seqn
(Der zweite Parameter muss eine geschachtelte Liste sein)
>
seqn:=proc(term::uneval, ll::uneval)
if type(ll,list) then
if type(ll[1],list) then
if nops(ll)=1 then
op(op(ll)):
[seq1(term,%)];
else
op(ll[1]):
ll[2..-1]:
[seq1( seqn(term, %), %%)];
end if:
else
op(ll);
[seq1(term,%)]:
end if:
else
error "Eingabe muss eine Liste oder eine geschachtelte Liste sein %1" ,ll:
end if:
end proc:
> x:='x': y:='y':
> seqn(x,[x=1..3]);
> seqn( x^y, [[x=0..3], [y=2..4]]);
> seqn( x^y, [[x=0..3], [y=0..x]]);
> n:='n': m:=1/Pi: x:=3: y:=4:
> seqn( n*m*x^y, [[x=0..3], [y=2..4]]);
trace seqn and seq1 to see how they work!
> trace(seqn,seq1):
> seqn( x^y, [[x=0..3], [y=0..x]]);
{--> enter seqn, args = x^y, [[x = 0 .. 3], [y = 0 .. x]]
{--> enter seq1, args = seqn(x^y,[[y = 0 .. x]]), x = 0 .. 3
{--> enter seqn, args = 0, [[y = 0 .. 0]]
{--> enter seq1, args = 0, y = 0 .. 0
<-- exit seq1 (now in seqn) = 0}
<-- exit seqn (now in seq1) = [0]}
{--> enter seqn, args = 1, [[y = 0 .. 1]]
{--> enter seq1, args = 1, y = 0 .. 1
<-- exit seq1 (now in seqn) = 1, 1}
<-- exit seqn (now in seq1) = [1, 1]}
{--> enter seqn, args = 2^y, [[y = 0 .. 2]]
{--> enter seq1, args = 2^y, y = 0 .. 2
<-- exit seq1 (now in seqn) = 1, 2, 4}
<-- exit seqn (now in seq1) = [1, 2, 4]}
{--> enter seqn, args = 3^y, [[y = 0 .. 3]]
{--> enter seq1, args = 3^y, y = 0 .. 3
<-- exit seq1 (now in seqn) = 1, 3, 9, 27}
<-- exit seqn (now in seq1) = [1, 3, 9, 27]}
<-- exit seq1 (now in seqn) = [0], [1, 1], [1, 2, 4], [1, 3, 9, 27]}
<-- exit seqn (now at top level) = [[0], [1, 1], [1, 2, 4], [1, 3, 9, 27]]}
> untrace(seqn,seq1):
>
seqn( x+y+z,[[x=1..2],
[y=10..20, 10],
[z=100..200, 100]]);
> n:='n': m:=1/Pi: x:=3: y:=4:
> seqn( n*m*x^y, [[x=0..3], [y=2..4]]);
Module
>
zähler:=module()
export nächste;
local zahl;
zahl:=0;
nächste:=proc()
zahl:=zahl+1;
end proc;
end module:
> zähler:-nächste();
> use zähler in nächste(),nächste(),nächste(); end use;
>
make_zähler:=proc(start)
local zahl,zähler;
zahl:=start;
zähler:=module()
export nächste;
nächste:=proc()
zahl:=zahl+1;
end proc;
end module:
end proc:
> z1:=make_zähler(5):z2:=make_zähler(0):
> z1:-nächste(),z2:-nächste();
>
>
>
make_stack:=proc()
local stack,stack_modul;
stack:=[];
stack_modul:=module()
export push,pop,empty;
push:=proc(Objekt)
stack:=[Objekt, op(stack)];
NULL;
end proc;
pop:=proc()
local erg;
if nops(stack)=0 then error "pop mit leerem Stack" end if;
erg:=stack[1];
stack:=stack[2..-1];
erg;
end proc:
empty:=proc()
is(nops(stack)=0);
end proc:
end module;
end proc:
> s1:=make_stack():
> s2:=make_stack():
> s1:-push(3);s2:-push(5);
> eval(op(7,eval(s1:-push)));
> eval(op(7,eval(s2:-push)));
> s1:-pop();
>
> eval(op(7,eval(s2:-push)));
> s1:-empty();
> s2:-empty();
> s2:-pop();
stringtools
Der folgende Modul stellt Funktionen zur Bearbeitung von Strings bereit
> restart:
>
stringtools:=module()
export left,right,mid,trim,ascii,upper,lower,
pos,vor,nach,split1,replace,frueher;
local i,pos1;
left:=(str::string,n::posint)->str[1..n];
right:=(str::string,n::posint)->str[-n..-1];
mid:=proc(str::string,lnks::posint,anz::posint)
if nargs=2 then
str[lnks..-1];
else
str[lnks..lnks+anz-1];
end if;
end proc;
trim:=proc(str::string)
local s0;
s0:=str;
while s0[1]=" " do
s0:=s0[2..-1];
end do;
s0;
end proc;
ascii:=(str::string)->op(convert(str[1],'bytes'));
upper:=proc(str::string)
local ka,kz,kae,kue,koe,ksz,dist,einsup;
ka:=ascii("a");
kz:=ascii("z");
kae:=ascii("ä");
koe:=ascii("ö");
kue:=ascii("ü");
ksz:=ascii("ß");
einsup:=proc(str)
local asc;
asc:=ascii(str);
if ((asc>=ka) and (asc<=kz)) or (asc=kae) or (asc=kue) or (asc=koe)
then
convert([asc-32],'bytes');
elif (asc=ksz)
then
"SS";
else
str;
end if
end proc;
cat(map(einsup,convert(str,'list'))[],"");
end proc;
lower:=proc(str::string)
local ka,kz,kae,kue,koe,dist,einsdown;
ka:=ascii("A");
kz:=ascii("Z");
kae:=ascii("Ä");
koe:=ascii("Ö");
kue:=ascii("Ü");
einsdown:=proc(str)
local asc;
asc:=ascii(str);
if ((asc>=ka) and (asc<=kz)) or (asc=kae) or (asc=kue) or (asc=koe)
then
convert([asc+32],'bytes');
else
str;
end if
end proc;
cat(map(einsdown,convert(str,'list'))[],"");
end proc;
pos := proc(muster::string,str::string,bereich::{range,integer})
local rng,p;
rng:=1..-1;
if nargs>2 then
if type(bereich,integer) then
rng:=bereich..-1;
else
rng:=bereich;
end if;
end if;
p:=searchtext(muster,str,rng);
if p>0 then
p+lhs(rng)-1;
else
0;
end if;
end proc;
vor:=proc(muster::string,str::string)
local i;
i:=searchtext(muster,str);
if i=0 then
str;
else
str[1..(i-1)];
end if;
end proc;
nach:=proc(muster::string,str::string)
local i;
i:=searchtext(muster,str);
if i=0 then
"";
else
str[i+length(muster)..-1]
end if;
end proc;
split1:=proc(muster::string,str::string)
local i;
i:=searchtext(muster,str);
if i=0 then
str,"";
else
str[1..(i-1)],str[i+length(muster)..-1];
end if
end proc;
replace:=proc(alt::string,neu::string,str::string)
local a,b;
a,b:=split1(alt,str);
if b="" then
str;
else
cat(a,neu,replace(alt,neu,b));
end if;
end proc;
frueher :=proc(str1::string,str2::string)
local s1,s2;
s1:=replace("Ü","UE",replace("Ö","UE",replace("Ä","AE",upper(str1))));
s2:=replace("Ü","UE",replace("Ö","UE",replace("Ä","AE",upper(str2))));
evalb(s1<s2);
end proc;
end module:
> with(stringtools);
> ascii("ß");
> upper("Häußer");
>
satz_worte:=proc(satz::string)
local w0,s1;
w0,s1:=stringtools:-split1(" ",satz);
if s1="" then
w0;
else
w0,satz_worte(s1);
end if;
end proc:
> satz1:="Der Habicht war so dicht wie lange nicht";
> satz_worte(satz1);
> sort([%],frueher);
>
Packages und Libraries
seq1, seqn, makestack und stringtoos müssen definiert sein. Öffnen Sie andernfalls den vorigen
Abschnitt und führen Sie dort die Definitionen durch.
saving and reading
> save seqn, seq1,make_stack,stringtools, `tools`: # text format
> save seqn, seq1,make_stack,stringtools, `tools.m`: # binary format
> restart:
libname:
savelibname:
> read `tools`:
> seqn(x^y, [[x=1..3], [y=1..3]]);
> s1:=make_stack(): s1:-push(13);s1:-pop();
> stringtools:-upper("häßliches Entlein");
building packages
> restart:
libname:
savelibname:
> read `tools`:
> mypack:=table():
> mypack[seqn]:=eval(seqn):
> mypack[seq1]:=eval(seq1):
> mypack[make_stack]:=eval(`make_stack`):
> mypack[seqn](x, [x=1..2, 0.5] );
> save mypack, `mypack.m`;
> restart:
libname:
savelibname:
> read `mypack.m`;
> with(mypack);
> seqn(x, [x=0..Pi, Pi/6]);
> restart:
libname:
savelibname:
> libname:=libname, `.`;
> with(mypack);
> seqn(x, [x=100..0, -10]);
Neue Libraries bzw. Repositories
Dieser Abschnitt setzt voraus, dass
# maple.ini
savelibname:="C:\\Programme\\Maple 6/mylib":
libname:=libname, savelibname:
print("initfile maple.ini"):
printf("libname: \n"):
print(libname):
printf("savelibname: \n"):
print(savelibname):
Packages in einer neuen Library speichern
> restart:
libname:
savelibname:
Der folgende Befehl darf nur einmal durchgeführt werden. Er erzeugt im angegebenen Verzeichnis eine neue Library
> march('create',savelibname,40);
> read `tools`:
> mypack:=table():
> mypack[seqn]:=eval(seqn):
> mypack[seq1]:=eval(seq1):
> mypack[make_stack]:=eval(make_stack):
>
savelib(mypack, `mypack.m`);
>
> savelib(stringtools);
>
Die Benutzung der beiden Packages
>
> restart:
libname:
savelibname:
> with(mypack);
> seqn(x,[x=3..1,-1]);
> with(stringtools);
Definition von mypack über eine Textdatei
mypack.mpl muss im currend-directory sein
> restart:
libname:
savelibname:
> read `mypack.mpl`:
Benutzung der Package (nichts neues)
> restart:
libname:
savelibname:
> with(mypack);
> seqn(x,[x=1..3]);
>
Zurück zum Inhaltsverzeichnis