Ubungen zur Algorithmischen Mathematik Blatt 4 - Dr. Kai

Werbung
Dr. Kai-Friederike Oelbermann
Dipl.-Math. Alina Bondarava
Wintersemester 2015/16
OVGU Magdeburg
Übungen zur Algorithmischen Mathematik
Blatt 4
1. Ersetzen Sie die geschachtelten if-else-Anweisungen in dem Programm Taschenrechner1.c aus
der Vorlesung durch switch-case. Die Wahl der Rechenart soll mit a-s-m-d gesteuert werden.
2. Ziel dieser Aufgabe ist es, das Sieb des Eratosthenes zu programmieren. Das Sieb findet alle
Primzahlen bis zu einer vorgegebenen Grenze N 2 N. Dafür stelle man sich vor, dass alle Zahlen
bis N aufgelistet sind. Zuerst wird die Eins gestrichen, sie ist keine Primzahl. Danach werden alle
Vielfachen der Zwei gestrichen, da diese keine Primzahlen sein können. Auch alle Vielfachen der
Drei werden als zusammengesetzte Zahlen gestrichen. Diese Prozedur wird mit allen Vielfachen
der nächsten ungestrichenen (Prim-)Zahl kleiner gleich N wiederholt. Übrig bleiben nur noch die
Primzahlen.
p
(a) Beweisen Sie, dass es ausreicht die Vielfachen aller Primzahlen kleiner oder gleich N zu
streichen, um alle Primzahlen bis N 2 N auszusieben.
(b) Programmieren Sie das Sieb des Eratosthenes. Listen Sie dazu die natürlichen Zahlen in
einem array der Maximallänge auf, die Ihr Computer Ihnen ermöglicht, d.h. Ihr Sieb soll
auch nur alle Primzahlen bis zu dieser Grenze finden können.
(c) Erweitern Sie Ihr Programm aus (b) so, dass es auch alle Primzahlzwillinge, -drillinge und
-vierlinge findet.
Hinweis: Primzahlzwillinge sind zwei aufeinanderfolgende Primzahlen pn und pn+1 mit
pn+1 pn = 2. Primzahldrillinge sind Primzahlen von der Form p, p + 2 und p + 6 sowie der spezielle Drilling 3, 5 und 7. Entsprechend sind Primzahlvierlinge Primzahlen von
der Form p, p + 2, p + 6 und p + 8.
3. (F5 PunkteF)
(a) Schreiben Sie ein Programm, welches die Fakultätsfunktion rekursiv berechnet, d.h. für die
Berechnung von (n 1)! in n! = n(n 1)! soll die Funktion selbst wieder aufgerufen werden.
(b) Sei n 2 N gerade. Beweisen Sie folgende Ungleichung
n!
Hinweis: Ordnen Sie n! = n(n
1)(n
⇣n⌘n
2
2
.
2) · . . . · 3 · 2 · 1 geschickt um.
4. (F5 PunkteF) Schreiben Sie ein naives Programm, welches zu zwei natürlichen Zahlen den
ggT (größten gemeinsamen Teiler) findet.
Die Beispielprogramme aus der Vorlesung und die Aufgabenblätter finden Sie unter http: // kai-friederike.
de/ wise2015algmathe. html .
Die mit F gekennzeichneten Aufgaben sind Hausaufgaben. Abgabe der Lösungen: 12.11.2015 vor der Vorlesung.
Beachten Sie die Hinweise zur Abgabe von Programmieraufgaben unter dem Link: http: // kai-friederike.
de/ wise2015algmathe. html
1
Musterlösungen
1. Der folgende Programmcode zeigt exemplarisch, wie man den switch-case Befehl verwendet.
1
#include <s t d i o . h>
2
3
4
5
6
double a d d i t i o n ( double a , double b )
{
return ( a+b ) ;
}
7
8
9
10
11
double s u b t r a k t i o n ( double a , double b )
{
return ( a b ) ;
}
12
13
14
15
16
double m u l t i p l i k a t i o n ( double a , double b )
{
return ( a ⇤b ) ;
}
17
18
19
20
21
22
23
24
25
26
27
28
29
double d i v i s i o n ( double a , double b , short ⇤w)
{
i f ( b <0.00000001 && b > 0.00000001)
{
⇤w=1;
return ( 0 ) ;
}
else
{
return ( a /b ) ;
}
}
30
31
32
33
34
35
i n t main ( void )
{
double z a h l 1 , z a h l 2 , e r g e b n i s ;
short warnung =0;
char wahl ;
36
37
38
39
p r i n t f ( " D i e s e s Programm kann e i n e d e r v i e r Grundrechenarten a u f z w e i \
r e e l l e Zahlen anwenden . \ n\
Geben S i e b i t t e I h r e e r s t e Zahl e i n : " ) ;
40
41
s c a n f ( "%l f " ,& z a h l 1 ) ;
42
43
p r i n t f ( "Geben S i e nun b i t t e I h r e z w e i t e Zahl e i n : " ) ;
44
45
46
s c a n f ( "%l f " ,& z a h l 2 ) ;
getchar ( ) ;
47
48
49
50
51
52
53
p r i n t f ( "Nun kommt d i e Wahl d e r Rechenart . B i t t e geben S i e e i n : \ n\
a f u e r Addition , \ n\
s f u e r S u b t r a k t i o n , \ n\
m f u e r M u l t i p l i k a t i o n , \ n\
d f u e r D i v i s i o n . \ n I h r e Wahl : " ) ;
s c a n f ( "%c " ,& wahl ) ;
54
55
56
57
58
59
60
61
62
switch ( wahl )
{
case ’ a ’ : e r g e b n i s=a d d i t i o n ( z a h l 1 , z a h l 2 ) ; break ;
case ’ s ’ : e r g e b n i s=s u b t r a k t i o n ( z a h l 1 , z a h l 2 ) ; break ;
case ’m ’ : e r g e b n i s=m u l t i p l i k a t i o n ( z a h l 1 , z a h l 2 ) ; break ;
case ’ d ’ : e r g e b n i s=d i v i s i o n ( z a h l 1 , z a h l 2 ,& warnung ) ; break ;
default : p r i n t f ( "Wegen I h r e r u n z u l a e s s i g e n Wahl wird das Programm\
b e e n d e t . \ n" ) ; return ( 1 ) ; break ;
2
}
63
64
65
66
67
68
i f ( warnung==0)
{
69
p r i n t f ( "Das E r g e b n i s d e r " ) ;
70
71
switch ( wahl )
{
case ’ a ’ : p r i n t f ( " A d d i t i o n " ) ; break ;
case ’ s ’ : p r i n t f ( " S u b t r a k t i o n " ) ; break ;
case ’m ’ : p r i n t f ( " M u l t i p l i k a t i o n " ) ; break ;
case ’ d ’ : p r i n t f ( " D i v i s i o n " ) ; break ;
}
72
73
74
75
76
77
78
79
p r i n t f ( " von %10.10 l f und %10.10 l f l a u t e t : %10.10 l f . \ n\n" , z a h l 1 , z a h l 2 , e r g e b n i s ) ;
80
81
i f ( z a h l 1 >100000000 | | ( z a h l 1 <0.00000001 && z a h l 1 > 0.00000001 ) | | \
z a h l 1 < 100000000 | | z a h l 2 >100000000 | | ( z a h l 2 <0.00000001 && \
z a h l 2 > 0.00000001 ) | | z a h l 2 < 100000000 )
{
p r i n t f ( " S i e muessen damit rechnen , d a s s d i e s e s E r g e b n i s wegen \
d e r G r o e s s e d e r Zahlen \ nmit R u n d u n g s f e h l e r n b e h a f t e t i s t . \ n" ) ;
}
else
{
p r i n t f ( " D i e s e s E r g e b n i s wird durch R u n d u n g s f e h l e r \
n i c h t w e s e n t l i c h v e r f a e l s c h t . \ n" ) ;
}
}
else
{
p r i n t f ( " Die D i v i s i o n konnte wegen e i n e s zu k l e i n e n Nenners \
n i c h t d u r c h g e f u e h r t werden . \ n" ) ;
}
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
return ( 0 ) ;
101
102
103
}
2. (a) Sei a ein Teiler von n, sodass n = ab mit a, b 2 N und a  b. Dann gilt
p
a2  ab = n =) a  n.
Damit muss mindestens ein Primfaktor einer zusammengesetzten Zahl immer kleiner gleich
der Wurzel der Zahl sein muss. Also ist es ausreichend, nur die Vielfachen von Zahlen zu
streichen, die kleiner oder gleich der Wurzel von N sind.
(b) Folgendes Programm gibt alle Primzahlen aus, die kleiner gleich einer eingegebenen Zahl N
sind.
1
2
#include <s t d i o . h>
#define MAXLAENGE 2000000
3
4
5
6
7
8
9
i n t main ( void )
{
unsigned i n t n=2 , i =0 , l =1 ,p=2 , a n z a h l =0;
unsigned i n t PF [MAXLAENGE] ;
char wahl =10;
10
11
12
/⇤ I n i t i a l i s i e r e Array mit Einsen ⇤/
3
13
14
15
16
f o r ( i =0; i <MAXLAENGE; i ++)
{
PF [ i ] = 1 ;
}
17
18
19
20
p r i n t f ( "Wir suchen a l l e Primzahlen k l e i n e r g l e i c h e i n e r \
n a t u e r l i c h e n Zahl N e c h t \n g r o e s s e r a l s 1 und k l e i n e r a l s %u . \ n \
B i t t e geben S i e e i n e s o l c h e Zahl e i n : " , MAXLAENGE) ;
21
22
23
s c a n f ( "%u" ,&n ) ;
getchar ( ) ;
24
25
26
27
28
while ( n<2 | | n> MAXLAENGE)
{
p r i n t f ( " B i t t e geben S i e e i n e Zahl g r o e s s e r a l s 1 und \
k l e i n e r a l s %u e i n : " ,MAXLAENGE ) ;
29
s c a n f ( "%u" ,&n ) ;
getchar ( ) ;
30
31
}
32
33
34
/⇤ S c h r e i b e i n das Array a l l e Z a h l e n von 2 b i s n⇤/
35
36
37
38
39
40
41
i =0;
while ( i<=n 2)
{
PF [ i ]= i +2;
i ++;
}
42
43
44
45
46
47
/⇤ S i e b d e s E r a t o s t h e n e s ⇤/
f o r ( i =0;( i +2)⇤( i +2)<=n ; i ++)
{
p=PF [ i ] ;
48
i f ( p !=1)
{
49
50
51
f o r ( l =2; l ⇤p<=n ; l ++)
{
PF [ ( l ⇤p 2)]=1;
}
52
53
54
55
56
}
57
58
}
59
60
61
62
63
/⇤ A u s g a b e s c h l e i f e mit Anzahl d e r Primz ahlen ⇤/
p r i n t f ( " \ n A l l e Primzahlen k l e i n e r g l e i c h %u s i n d : \ n" , n ) ;
64
65
66
f o r ( i =0; i <MAXLAENGE; i ++)
{
67
68
69
70
71
72
73
}
i f (PF [ i ] ! = 1 )
{
p r i n t f ( " %u " ,PF [ i ] ) ;
a n z a h l=a n z a h l +1;
}
74
75
p r i n t f ( " \n\ nAnzahl d e r Primzahlen : %u\n\n" , a n z a h l ) ;
76
77
/⇤ Frage nach P r i m z a h l h a e u f u n g e n ⇤/
4
78
p r i n t f ( " Wollen S i e auch a l l e P r i m z a h l z w i l l i n g e ,
d r i l l i n g e und v i e r l i n g e \
k l e i n e r g l e i c h %u ausgeben ?\ n Fuer Z w i l l i n g e geben S i e b i t t e <z >, \
D r i l l i n g e <d>, V i e r l i n g e <v> und zum Beenden e i n \n\
anderes b e l i e b i g e s Zeichen ein : " ,n ) ;
79
80
81
82
83
s c a n f ( "%c " ,& wahl ) ;
84
85
/⇤ Z w i l l i n g e ⇤/
86
87
i f ( wahl==’ z ’ )
{
f o r ( i =0; i +2<MAXLAENGE; i ++)
{
88
89
90
91
92
93
94
95
96
97
}
98
}
i f (PF [ i ] ! = 1 && PF [ i +2]!=1)
{
p r i n t f ( " %u , %u ; \ n" ,PF [ i ] , PF [ i + 2 ] ) ;
}
99
/⇤ D r i l l i n g e ⇤/
100
101
i f ( wahl==’ d ’ )
{
102
103
104
i f ( n>=7) p r i n t f ( " 3 , 5 , 7 ; \ n" ) ;
105
106
f o r ( i =0; i +6<MAXLAENGE; i ++)
{
107
108
109
i f (PF [ i ] ! = 1 && PF [ i +2]!=1 && PF [ i +6]!=1)
{
110
111
112
113
}
114
115
}
116
}
p r i n t f ( " %u , %u , %u ; \ n" ,PF [ i ] , PF [ i +2] ,PF [ i + 6 ] ) ;
117
/⇤ V i e r l i n g e ⇤/
118
119
i f ( wahl==’ v ’ )
{
f o r ( i =0; i +8<MAXLAENGE; i ++)
{
120
121
122
123
124
i f (PF [ i ] ! = 1 && PF [ i +2]!=1 && PF [ i +6]!=1&& PF [ i +8]!=1)
{
125
126
127
128
}
129
130
131
132
133
134
}
p r i n t f ( " %u , %u , %u , %u ; \ n" ,PF [ i ] , PF [ i +2] ,PF [ i +6] ,PF [ i + 8 ] ) ;
}
}
p r i n t f ( " \n" ) ;
return ( 0 ) ;
3. Dieses Programm berechnet der Fakultätsfunktion rekursiv
1
#include <s t d i o . h>
2
3
4
5
6
long f a k u l t a e t ( short a )
{
long e r g e b n i s =1;
short i =1;
5
7
8
9
10
11
12
13
14
}
i f ( a==0 | |
a==1)
{
return ( 1 ) ;
}
e r g e b n i s=f a k u l t a e t ( a 1)⇤ a ;
return ( e r g e b n i s ) ;
15
16
17
18
i n t main ( void )
{
short v a r i a b l e =0;
19
p r i n t f ( " D i e s e s Programm b e r e c h n e t den Wert d e r F a k u l t a e t s f u n k t i o n zu einem \
von Ihnen e i n g e g e b e n e n Wert . \ n B i t t e geben S i e I h r e n Wert e i n : " ) ;
20
21
22
s c a n f ( "%h i " , &v a r i a b l e ) ;
23
24
i f ( v a r i a b l e <0)
{
p r i n t f ( " D i e s e r Wert i s t u n z u l a e s s i g . Wir beenden das Programm . \ n\n" ) ;
return ( 1 ) ;
}
25
26
27
28
29
30
31
32
33
34
35
36
i f ( v a r i a b l e >19)
{
p r i n t f ( " Die e i n g e g e b e n e Zahl i s t zu g r o s s ; das kann u n s e r Computer n i c h t . \ n\
Wir beenden das Programm . \ n\n" ) ;
return ( 1 ) ;
}
37
p r i n t f ( " Die F a k u l t a e t von %h i l a u t e t : \ n %l i . \ n\n" ,
variable , fakultaet ( variable ) ) ;
38
39
40
41
42
}
return ( 0 ) ;
Wir beweisen nun die Ungleichung n!
n! = n(n
|
1)(n
(n/2)n/2 für gerade n 2 N. Zunächst gilt
2) · · · (n/2 + 1) (n/2)(n/2 1) · · · 1
{z
}|
{z
}
n/2 Faktoren
n/2 Faktoren,
1
n (n 1) (n 2) · · · (n/2 + 1) (n/2 Faktoren)
|{z}
| {z } | {z }
| {z }
n/2
(n/2)
n/2
n/2
n/2
n/2
.
4. Dieses Programm berechnet den größten gemeinsamen Teiler zweier natürlicher Zahlen ohne den
Euklidischen Algorithmus
1
#include <s t d i o . h>
2
3
4
5
i n t main ( void )
{
unsigned z a h l 1 =1, z a h l 2 =1 , g g t =1, i =1;
6
7
8
p r i n t f ( " D i e s e s Programm b e r e c h n e t den g r o e s s t e n gemeinsamen T e i l e r \
z w e i e r n a t u e r l i c h e r Zahlen . \ n B i t t e geben S i e I h r e e r s t e Zahl e i n : " ) ;
9
10
s c a n f ( "%u" ,& z a h l 1 ) ;
11
12
p r i n t f ( " B i t t e geben S i e nun I h r e z w e i t e Zahl e i n : " ) ;
13
14
s c a n f ( "%u" ,& z a h l 2 ) ;
15
6
/⇤ P r o b i e r e a l l e p o t e n t i e l l e n T e i l e r durch ⇤/
16
17
while ( i<=z a h l 1 && i<=z a h l 2 )
{
i f ( z a h l 1%i ==0 && z a h l 2%i ==0)
{
g g t=i ;
}
i ++;
}
18
19
20
21
22
23
24
25
26
p r i n t f ( " Der g r o e s s t e gemeinsame T e i l e r von %u und %u i s t %u . " , z a h l 1 , z a h l 2 , g g t ) ;
27
28
p r i n t f ( " \n\n" ) ;
29
30
31
32
}
return ( 0 ) ;
7
Herunterladen