Kesalahan pembulatan selama transisi

Di Bavaria, nilai rata-rata keseluruhan \(2{,}33\) menjamin kelayakan untuk Gymnasium \(2{,}34\) tidak. Pada batas yang sangat tipis ini, urutan dua operasi pembulatan dapat menentukan di sisi mana seorang anak berada. Günther Felbinger membahas konsekuensi potensial dari efek pembulatan ini dalam sebuah postingan blog . Karena penasaran, saya sendiri menghitung efeknya di semua kombinasi nilai yang diizinkan dalam model tersebut.


Pertanyaan utama saya adalah: Seberapa sering pembulatan awal ke nilai mata pelajaran secara keseluruhan menghasilkan jenis perhitungan sekolah yang berbeda dibandingkan dengan perhitungan menggunakan rata-rata mata pelajaran yang tidak dibulatkan? Lebih lanjut, akan menarik untuk melihat perubahan apa yang terjadi jika rata-rata mata pelajaran individu (seperti yang disarankan di sana) awalnya dibulatkan hanya ke satu tempat desimal.

Menurut Pasal 6 Peraturan Sekolah Dasar Bavaria, nilai rata-rata dihitung dari nilai Bahasa Jerman, Matematika, dan Studi Lokal dan Umum. Peraturan pelaksanaannya menetapkan batas hingga \(2{,}33\) dan hingga \(2{,}66\) . Dalam model perhitungan berikut, setiap rata-rata keseluruhan dibulatkan hingga dua desimal dan tidak dibulatkan lagi. Jadi, misalnya...

\[
\frac{2{,}33+2{,}34+2{,}34}{3}=2{,}3366\ldots \longrightarrow 2{,}33.
\]

Hal ini sangat penting untuk klasifikasi: \(2{,}3366\ldots\) tidak menjadi \(2{,}34\) , tetapi \(2{,}33\) dan oleh karena itu masih cukup untuk sekolah menengah atas.

Entri awal mengilustrasikan pembulatan awal dengan nilai rata-rata spesifik mata pelajaran yang diasumsikan \(1{,}6\) , \(2{,}6\) , dan \(2{,}6\) . Dari nilai-nilai ini, nilai keseluruhan \(2\) , \(3\) , dan \(3\) pertama kali diturunkan. Rata-ratanya adalah

\[
\frac{2+3+3}{3}=2{,}6666\ldots \longrightarrow 2{,}66,
\]

yang berarti siswa tersebut tidak memenuhi syarat untuk masuk sekolah dasar. Namun, tanpa pembulatan ke nilai bulat, hasil dalam contoh hipotetis tersebut akan menjadi...

\[
\frac{1{,}6+2{,}6+2{,}6}{3}=2{,}2666\ldots \longrightarrow 2{,}26.
\]

Pada contoh kedua, pembulatan bekerja ke arah yang berlawanan: \(2{,}4\) , \(3{,}4\) dan \(2{,}4\) menjadi nilai not penuh \(2\) , \(3\) dan \(2\) , secara resmi \(2{,}33\) . Namun, nilai yang tidak dibulatkan menghasilkan \(2{,}73\) . Contoh-contoh tersebut dengan jelas menunjukkan efeknya. Namun, contoh-contoh tersebut belum mengungkapkan seberapa sering hal itu terjadi atau apa konsekuensi dari metode pembulatan yang berbeda.

Oleh karena itu, untuk perhitungan saya, saya menggunakan ruang hasil yang jelas. Setiap rata-rata subjek dapat berupa salah satu dari \(501\) nilai di dalamnya.

\[
1{,}00,\, 1{,}01,\, 1{,}02,\, \ldots, \, 5{,}99, \, 6{,}00
\]

Misalkan saya memberikan bobot yang sama pada semua kombinasi berurutan dari bahasa Jerman, matematika, dan studi lokal serta umum. Dengan demikian, ada

\[
501^3=125\,751\,501
\]

Kasus-kasus. Oleh karena itu, model ini tidak ambigu, tetapi artifisial: Model ini mengasumsikan rata-rata mata pelajaran yang terdistribusi secara merata, independensi ketiga mata pelajaran, dan langkah tepat seperseratus. Model ini tidak mencerminkan distribusi sebenarnya dari anak-anak sekolah dasar di Bavaria.

Untuk tiga subjek rata-rata \(d,m,h\) kita tulis

\[
A(d,m,h)=\frac{\left\lfloor 100\cdot\frac{d+m+h}{3}\right\rfloor}{100}
\]

untuk rata-rata keseluruhan yang dibulatkan hingga dua angka desimal. Sekarang kita bandingkan tiga metode perhitungan.:

\[
\begin{aligned}
A_0 &= A(\operatorname{round}(d),\operatorname{round}(m),\operatorname{round}(h)),\\
A_1 &= A(\operatorname{round}_1(d),\operatorname{round}_1(m),\operatorname{round}_1(h)),\\
A_\mathrm{ref} &= A(d,m,h).
\end{aligned}
\]

\(A_0\) sesuai dengan perhitungan menggunakan nilai bulat, \(A_1\) untuk usulan dengan satu angka desimal, dan \(A_\mathrm{ref}\) untuk referensi yang tidak dibulatkan dalam model. Perhitungan ini dapat diimplementasikan langsung di Rust , misalnya.:

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
        );
    }
}

Toleransi kecil pada calculate_average mencegah nilai seperti \(2{,}67\) karena representasi floating point binernya, ia secara keliru dianggap \(2{,}669999\ldots\) terputus. normalize_grade Selain itu, ia mereduksi setiap nilai loop kembali ke grid orde keseratus. Setidaknya ada dua nilai rata-rata berbeda yang mungkin. \(1/300\) terpisah; toleransi dari \(10^{-9}\) Oleh karena itu, ukurannya cukup kecil sehingga tidak mengubah kasus yang benar-benar berada di ambang batas.

Program tersebut dikompilasi dan dijalankan dengan

rustc -O calc.rs && ./calc

Program ini melakukan iterasi melalui semua \(125\,751\,501\) kombinasi dan mengembalikan:

PerbandinganBagian
Nilai bulat versus rata-rata mata pelajaran yang belum dibulatkan\(10{,}4411\,\%\)
Nilai keseluruhan dibandingkan dengan proposal dengan satu angka desimal.\(10{,}1521\,\%\)
Proposal dengan satu angka desimal dibandingkan dengan rata-rata ahli yang tidak dibulatkan\(0{,}6615\,\%\)

Nilai utama bagi saya adalah \(10{,}4411\,\%\): Dalam lebih dari satu dari sepuluh kombinasi, pembulatan awal ke nilai bulat menghasilkan tipe sekolah yang dihitung berbeda dari referensi yang tidak dibulatkan. Proporsi ini secara eksklusif menggambarkan efek pembulatan dalam model yang dipilih.

Penggunaan rata-rata ahli dengan satu angka desimal akan menghasilkan klasifikasi yang berbeda pada \(10{,}1521\,\%\) dari semua kasus model dibandingkan dengan metode sebelumnya. Namun, perbandingan ketiga sangat penting: dibandingkan dengan referensi yang tidak dibulatkan, metode dengan satu angka desimal hanya menyisakan \(0{,}6615\,\%\) kasus yang menyimpang. Dengan demikian, penyimpangan dari referensi berkurang sebesar...

\[
1-\frac{0{,}6615}{10{,}4411}\approx 93{,}7\,\%.
\]

Bagi saya, inilah konsekuensi yang patut dipertanyakan dari metode perhitungan saat ini: pencapaian spesifik mata pelajaran yang diasumsikan tetap tidak berubah; hanya titik waktu pembulatan yang dapat mengubah jenis sekolah yang dihitung. Meskipun perhitungan dengan satu angka desimal tidak sepenuhnya menghilangkan efek ini, hal itu secara signifikan menguranginya dalam model.

Namun, angka-angka ini tidak memberi tahu kita berapa banyak anak yang sebenarnya terpengaruh. Nilai rapor tidak selalu dihasilkan sebagai rata-rata yang dibulatkan secara mekanis, prestasi akademik tidak terdistribusi secara merata atau independen, dan pilihan jenis sekolah yang sebenarnya tidak hanya bergantung pada ketiga angka ini. Perhitungan saya menjawab pertanyaan yang lebih spesifik: Seberapa sering pembulatan mengubah nilai yang dihitung ketika semua kombinasi nilai perseratusan memiliki kemungkinan yang sama?

Terakhir, perbandingan dengan postingan asli: Tingkat keseluruhan yang disebutkan di sana, sekitar \(10\,\%\) mendekati angka saya yaitu \(10{,}4411\,\%\) . Namun, perhitungan saya tidak mengkonfirmasi empat kasus individual, yang masing-masing dilaporkan sebagai \(1/6 \approx 17\,\%\) Untuk "tidak masuk sekolah menengah dengan \(3{,}00\) ", "tidak masuk sekolah menengah atas dengan \(2{,}33\) ", "berhasil masuk sekolah menengah atas dengan \(2{,}66\) ", dan "berhasil masuk sekolah menengah dengan \(2{,}66\) \(1{,}4615\,\%\) \(59{,}6096\,\%\) \(1{,}2023\,\%\) \(62{,}9395\,\%\) .

Keempat nilai tersebut adalah probabilitas bersyarat dengan kelompok referensi yang ukurannya berbeda. Tanpa ruang sampel yang didefinisikan secara berbeda \(1/6\) tidak dapat diturunkan dari nilai-nilai tersebut. Perhitungan saya dengan demikian mengkonfirmasi efek pembulatan, tetapi bukan probabilitas individual ini. Bagaimanapun, pernyataan tentang jumlah sebenarnya anak yang terdampak akan membutuhkan distribusi nilai sebenarnya dan ketergantungannya.

Kembali