Funksjonen under regner ut omkretsen av en sirkel. Er den vektorisert?
f.m
function y = f(x)
y = 2 * pi * x;
end
Videoforklaring (5:07)
Svar
Ja, funksjonen lar oss regne ut en mengde omkretser på en gang ved å utnytte Matlabs innebygde operasjoner.
Oppgave 5.1.2: Vektoriserte funksjoner
Funksjonen under regner ut arealet av en sirkel. Er den vektorisert? Hvordan kan den eventuelt vektoriseres?
g.m
function y = g(x)
y = pi * x ^ 2;
end
Videoforklaring (3:54)
Svar
Nei, for funksjonen lar oss ikke regne ut svar for hele vektorer av gangen. Den kunne blitt vektorisert med bruk av elementvis opphøyd-i.
Oppgave 5.1.3: Vektoriserte funksjoner
Funksjonen under regner ut verdien som tilsvarer et romersiffer. Er den vektorisert? Hvordan kan den eventuelt vektoriseres?
fra_romersiffer.m
function retur = fra_romersiffer(siffer)
switch siffer
case 'I', verdi = 1;
case 'V', verdi = 5;
case 'X', verdi = 10;
case 'L', verdi = 50;
case 'C', verdi = 100;
case 'D', verdi = 500;
case 'M', verdi = 1000;
end
retur = verdi;
end
Videoforklaring (10:48)
Svar
Den er ikke vektorisert, for den bruker ikke Matlabs innebygde operasjoner eller funksjoner og den kan heller ikke regne ut resultat for en hel vektor av verdier av gangen. Det er generelt vanskelig å vektorisere kode som trenger å bruke switch-setninger, siden de gjerne har mye sprikende oppførsel som det er vanskelig å uttrykke med én eller et lite knippe innebygde funksjoner og operasjoner. Det finnes en måte å gjøre det på her (se utdelt kode i oppgave 5.2.6), men generelt er det beste vi kan gjøre å lage en "liksom-vektorisert"-funksjon vha en for-løkke som behandler ett og ett element i parameteren. Ved å gjøre dette, kan kode som bruker funksjonen fortsatt skrives vektorisert.
Oppgave 5.1.4: Preallokering
Hva er ineffektivt med funksjonen som står i filen under? Hvordan kan den forbedres?
fib.m
function retur = fib(n)
retur = [0, 1];
for i = 3:n
retur(i) = retur(i-1) + retur(i-2);
end
retur = retur(1:n);
end
Videoforklaring (8:21)
Svar
Listen retur vokser med ett element for hver iterasjon i løkken. Det fører til mye kopiering av data. Den forbedres hvis man før for-løkken binder retur til en vektor med plass til alle elementene som skal produseres.
Oppgave 5.1.5: Preallokering
Er preallokering nødvendig i funksjonen under?
diff.m
function retur = diff_2(x)
retur = x(2:end) - x(1:end-1);
end
Videoforklaring (4:42)
Svar
Nei, koden er vektorisert og produserer hele resultatlisten på en gang. Preallokering er bare nødvendig hvis vi produserer ett og ett element av gangen i en selvskrevet løkke.
Kodeoppgaver
Oppgave 5.2.1: Samlet Fahrenheitoversikt
Du har tidligere laget et script som konverterer Celsius-verdier en bruker skriver inn fortløpende til Fahrenheit. For at utskriften fra scriptet skal bli mer oversiktlig, ønsker du å samle all utskriften i stedet for at den kommer fortløpende.
Endre scriptet slik at utskriften kommer først etter at brukeren har skrevet inn alle Celsius-verdiene. Konverteringene skal også skrives ut i rekkefølge etter stigende Celsius-verdi.
Utdelt kode
fahrenheit.m
svar = input('Ønsker du å skrive inn egne Celsius-verdier? (ja/nei) ', 's');
if strcmp(svar, 'ja')
celsius = les_inn_tall('Skriv inn Celsius-verdi: ');
while ~isempty(celsius)
skriv_ut_fahr(celsius);
celsius = les_inn_tall('Skriv inn Celsius-verdi: ');
end
else
skriv_ut_fahr(-20);
skriv_ut_fahr(0);
skriv_ut_fahr(18);
skriv_ut_fahr(37);
skriv_ut_fahr(100);
end
les_inn_tall.m
function retur = les_inn_tall(melding)
tallstr = input(melding, 's');
tall = str2double(tallstr);
er_ugyldig = isnan(tall);
while er_ugyldig && ~isempty(tallstr)
fprintf('Teksten %s kan ikke tolkes som et tall\n', tallstr);
tallstr = input(melding, 's');
tall = str2double(tallstr);
er_ugyldig = isnan(tall);
end
if isempty(tallstr)
retur = [];
else
retur = tall;
end
end
skriv_ut_fahr.m
function skriv_ut_fahr(celsius)
fahr = cels2fahr(celsius);
fprintf('Celsiusverdi %.2f tilsvarer Fahrenheitverdi %.2f\n', celsius, fahr);
end
cels2fahr.m
function retur = cels2fahr(celsius)
retur = 9/5*celsius + 32;
end
Videoforklaring (mm:ss)
Del 1 (mm:ss)
Del 2 (mm:ss)
Løsningsforslag
fahrenheit.m
svar = input('Ønsker du å skrive inn egne Celsius-verdier? (ja/nei) ', 's');
if strcmp(svar, 'ja')
celsius = les_inn_tall('Skriv inn Celsius-verdi: ');
les_inn_flere = ~isempty(celsius);
while les_inn_flere
siste_verdi = les_inn_tall('Skriv inn Celsius-verdi: ');
les_inn_flere = ~isempty(siste_verdi);
celsius = [celsius, siste_verdi];
end
celsius = sort(celsius);
skriv_ut_fahr(celsius);
else
skriv_ut_fahr([-20, 0, 18, 37, 100]);
end