I Bayern intygar ett genomsnittligt betyg på \(2{,}33\) lämplighet för gymnasiet \(2{,}34\) inte gör det. Vid denna skarpa gräns kan ordningen på två avrundningsoperationer avgöra vilken sida ett barn hamnar på. Günther Felbinger diskuterar de potentiella konsekvenserna av denna avrundningseffekt i ett blogginlägg . Av rent intresse beräknade jag själv effekterna för alla betygskombinationer som är tillåtna i modellen.
Min centrala fråga är: Hur ofta leder tidig avrundning till hela ämnesbetyg till en annan typ av skolberäkning än beräkningar med oavrundade ämnesmedelvärden? Dessutom vore det intressant att se vad som förändras om medelvärdena för de enskilda ämnena (som föreslås där) initialt avrundas till endast en decimal.
Enligt avsnitt 6 i de bayerska grundskolereglerna beräknas medelbetyget utifrån betygen i tyska, matematik samt lokala och allmänna studier. Tillämpningsföreskrifterna anger gränserna upp till och inklusive \(2{,}33\) och upp till och inklusive \(2{,}66\) . I följande beräkningsmodell avkortas varje totalmedelvärde till två decimaler och avrundas inte igen. Således, till exempel...
\[
\frac{2{,}33+2{,}34+2{,}34}{3}=2{,}3366\ldots \longrightarrow 2{,}33.
\]
Detta är avgörande för klassificeringen: \(2{,}3366\ldots\) blir inte \(2{,}34\) , utan \(2{,}33\) och är därför fortfarande tillräckligt för grundskolan.
Den initiala posten illustrerar tidig avrundning med de antagna ämnesspecifika medelvärdena \(1{,}6\) , \(2{,}6\) och \(2{,}6\) . Från dessa härleds först hela betygen \(2\) , \(3\) och \(3\) Deras medelvärde är
\[
\frac{2+3+3}{3}=2{,}6666\ldots \longrightarrow 2{,}66,
\]
vilket innebär att eleven inte kvalificerar sig för direkt antagning till grundskolan. Utan avrundning till hela betyg skulle dock resultatet i det hypotetiska exemplet bli...
\[
\frac{1{,}6+2{,}6+2{,}6}{3}=2{,}2666\ldots \longrightarrow 2{,}26.
\]
I det andra exemplet fungerar avrundningen i motsatt riktning: \(2{,}4\) , \(3{,}4\) och \(2{,}4\) blir hela notvärden \(2\) , \(3\) och \(2\) , officiellt \(2{,}33\) . De avrundade värdena resulterar dock i \(2{,}73\) . Exemplen visar tydligt effekten. De avslöjar dock ännu inte hur ofta det inträffar eller vilka konsekvenserna av en annan avrundningsmetod skulle bli.
Därför använder jag ett tydligt resultatutrymme för min beräkning. Varje subjektmedelvärde kan vara ett av \(501\) -värdena inom det.
\[
1{,}00,\, 1{,}01,\, 1{,}02,\, \ldots, \, 5{,}99, \, 6{,}00
\]
Antag. Jag viktar alla ordnade kombinationer av tyska, matematik samt lokala och allmänna studier lika. Således finns det
\[
501^3=125\,751\,501
\]
Fall. Modellen är därför entydig, men artificiell: Den antar jämnt fördelade ämnesmedelvärden, de tre ämnenas oberoende och steg på exakt en hundradel. Den återspeglar inte den faktiska fördelningen av bayerska grundskolebarn.
För tre subjektsmedel \(d,m,h\) skriver vi
\[
A(d,m,h)=\frac{\left\lfloor 100\cdot\frac{d+m+h}{3}\right\rfloor}{100}
\]
för det totala genomsnittet avkortat till två decimaler. Nu jämför vi tre beräkningsmetoder.:
\[
\begin{aligned}
A_0 &= A(\operatorname{runda}(d),\operatorname{runda}(m),\operatorname{runda}(h)),\\
A_1 &= A(\operatorname{runda}_1(d),\operatorname{runda}_1(m),\operatorname{runda}_1(h)),\\
A_\mathrm{ref} & = A(d,m,h).
\end{aligned}
\]
\(A_0\) motsvarar beräkningen med hela betyg, \(A_1\) förslaget med en decimal, och \(A_\mathrm{ref}\) den oavrundade referensen inom modellen. Beräkningen kan till exempel implementeras direkt i Rust .:
const SCHOOL_GYMNASIUM: i32 = 0;
const SCHOOL_REALSCHULE: i32 = 1;
const SCHOOL_MITTELSCHULE: i32 = 2;
const FLOAT_TOLERANCE: f64 = 1e-9;
#[derive(Clone, Copy, Default)]
struct Statistic {
conflict_count: u64,
total_count: u64,
}
fn determine_school(average: f64) -> i32 {
if average <= 2.33 {
return SCHOOL_GYMNASIUM;
}
if average <= 2.66 {
return SCHOOL_REALSCHULE;
}
SCHOOL_MITTELSCHULE
}
fn calculate_average(note_deutsch: f64, note_mathe: f64, note_hsu: f64) -> f64 {
let average = (note_deutsch + note_mathe + note_hsu) / 3.0;
((average + FLOAT_TOLERANCE) * 100.0).floor() / 100.0
}
fn round_to_whole_grade(grade: f64) -> f64 {
grade.round()
}
fn round_to_one_decimal(grade: f64) -> f64 {
(grade * 10.0).round() / 10.0
}
fn normalize_grade(grade: f64) -> f64 {
(grade * 100.0).round() / 100.0
}
fn percentage(count: u64, total: u64) -> f64 {
count as f64 / total as f64 * 100.0
}
fn main() {
let mut combination_count = 0;
let mut official_reference_conflicts = 0;
let mut official_proposal_conflicts = 0;
let mut proposal_reference_conflicts = 0;
let mut statistics = [Statistic::default(); 4];
let mut note_deutsch = 1.0;
while note_deutsch <= 6.0 {
let mut note_mathe = 1.0;
while note_mathe <= 6.0 {
let mut note_hsu = 1.0;
while note_hsu <= 6.0 {
combination_count += 1;
let official_average = calculate_average(
round_to_whole_grade(note_deutsch),
round_to_whole_grade(note_mathe),
round_to_whole_grade(note_hsu),
);
let proposed_average = calculate_average(
round_to_one_decimal(note_deutsch),
round_to_one_decimal(note_mathe),
round_to_one_decimal(note_hsu),
);
let reference_average =
calculate_average(note_deutsch, note_mathe, note_hsu);
let official_school = determine_school(official_average);
let proposed_school = determine_school(proposed_average);
let reference_school = determine_school(reference_average);
if official_average == 3.0 {
statistics[0].total_count += 1;
if reference_school != SCHOOL_MITTELSCHULE {
statistics[0].conflict_count += 1;
}
}
if official_average == 2.66 {
statistics[1].total_count += 1;
if reference_school == SCHOOL_GYMNASIUM {
statistics[1].conflict_count += 1;
}
}
if official_average == 2.33 {
statistics[2].total_count += 1;
if reference_school != SCHOOL_GYMNASIUM {
statistics[2].conflict_count += 1;
}
}
if official_average == 2.66 {
statistics[3].total_count += 1;
if reference_school == SCHOOL_MITTELSCHULE {
statistics[3].conflict_count += 1;
}
}
if official_school != reference_school {
official_reference_conflicts += 1;
}
if official_school != proposed_school {
official_proposal_conflicts += 1;
}
if proposed_school != reference_school {
proposal_reference_conflicts += 1;
}
note_hsu = normalize_grade(note_hsu + 0.01);
}
note_mathe = normalize_grade(note_mathe + 0.01);
}
note_deutsch = normalize_grade(note_deutsch + 0.01);
}
println!(
"official/reference: {}%",
percentage(official_reference_conflicts, combination_count)
);
println!(
"official/proposal: {}%",
percentage(official_proposal_conflicts, combination_count)
);
println!(
"proposal/reference: {}%",
percentage(proposal_reference_conflicts, combination_count)
);
for (index, statistic) in statistics.iter().enumerate() {
println!(
"#{}: {}% ({}/{})",
index + 1,
percentage(statistic.conflict_count, statistic.total_count),
statistic.conflict_count,
statistic.total_count
);
}
}
Den lilla toleransen i calculate_average förhindrar ett värde som \(2{,}67\) på grund av dess binära flyttalrepresentation ansågs den felaktigt \(2{,}669999\ldots\) är avskuren. normalize_grade Dessutom reduceras varje loopvärde tillbaka till ett hundrateordningens rutnät. Minst två olika möjliga medelvärden finns. \(1/300\) isär; toleransen för \(10^{-9}\) är därför tillräckligt liten för att inte ändra något verkligt gränsfall.
Programmet kompileras och startas med
rustc -O calc.rs && ./calc
Programmet itererar genom alla \(125\,751\,501\) kombinationer och returnerar:
| Jämförelse | Del |
| Hela betyg kontra oavrundade ämnesmedelvärden | \(10{,}4411\,\%\) |
| Hela betyg jämfört med förslaget med en decimal | \(10{,}1521\,\%\) |
| Förslag med en decimal jämfört med oavrundade expertmedelvärden | \(0{,}6615\,\%\) |
Det centrala värdet för mig är \(10{,}4411\,\%\): I mer än en av tio kombinationer leder tidig avrundning till hela betyg till en annan beräknad skoltyp än den avrundade referensen. Denna andel beskriver uteslutande avrundningseffekten inom den valda modellen.
Att byta till expertmedelvärden med en decimal skulle leda till en annan klassificering i \(10{,}1521\,\%\) av alla modellfall jämfört med den tidigare metoden. Den tredje jämförelsen är dock avgörande: jämfört med den oavrundade referensen lämnar metoden med en decimal endast \(0{,}6615\,\%\) avvikande fall. Avvikelsen från referensen minskar därmed med
\[
1-\frac{0{,}6615}{10{,}4411}\approx 93{,}7\,\%.
\]
Detta är, för mig, just den tvivelaktiga konsekvensen av den nuvarande beräkningsmetoden: de antagna ämnesspecifika prestationerna förblir oförändrade; endast tidpunkten då avrundning sker kan ändra den beräknade skoltypen. Även om beräkning med en decimal inte helt eliminerar denna effekt, minskar den den avsevärt inom modellen.
Dessa siffror säger oss dock inte hur många barn som faktiskt påverkas. Betygen på betygsrapporter genereras inte nödvändigtvis som mekaniskt avrundade medelvärden, de akademiska prestationerna är varken jämnt fördelade eller oberoende, och det faktiska valet av skoltyp beror inte enbart på dessa tre siffror. Min beräkning besvarar en mer specifik fråga: Hur ofta ändrar avrundning det beräknade betyget när alla hundradelskombinationer är lika sannolika?
Slutligen, en jämförelse med det ursprungliga inlägget: Den totala andelen som nämns där, cirka \(10\,\%\) ligger nära mina \(10{,}4411\,\%\) . Mina beräkningar bekräftar dock inte de fyra individuella fallen, som vart och ett rapporteras som \(1/6 \approx 17\,\%\) För "missade gymnasiet med \(3{,}00\) ", "missade grundskolan med \(2{,}33\) ", "uppnådde grundskolan med \(2{,}66\) " och "uppnådde gymnasiet med \(2{,}66\) \(1{,}4615\,\%\) \(59{,}6096\,\%\) \(1{,}2023\,\%\) \(62{,}9395\,\%\) .
De fyra värdena är villkorade sannolikheter med referensgrupper av olika storlek. Utan ett annorlunda definierat urvalsutrymme kan \(1/6\) inte härledas från dem. Min beräkning bekräftar således avrundningseffekten, men inte dessa individuella sannolikheter. I vilket fall som helst skulle uttalanden om det faktiska antalet berörda barn kräva verkliga betygsfördelningar och deras beroenden.