Помилки округлення під час переходу

У Баварії загальний середній бал \(2{,}33\) засвідчує придатність для гімназії \(2{,}34\) – ні. При такому різкому граничному значенні порядок двох операцій округлення може визначити, на яку сторону потрапляє дитина. Гюнтер Фельбінгер обговорює потенційні наслідки цього ефекту округлення в блозі . З чистого інтересу я сам розрахував ефекти для всіх комбінацій класів, дозволених у моделі.


Моє головне питання: як часто раннє округлення до цілих предметних оцінок призводить до іншого типу шкільного розрахунку, ніж розрахунки з використанням неокруглених середніх значень за предметами? Крім того, було б цікаво подивитися, що зміниться, якщо середні значення окремих предметів (як там пропонується) спочатку округлити лише до одного знака після коми.

Згідно з розділом 6 Баварських правил початкової школи, середній бал розраховується на основі оцінок з німецької мови, математики та місцевого та загального краєзнавства. У впровадженні встановлені межі до \(2{,}33\) та до \(2{,}66\) . У наступній моделі розрахунку кожен загальний середній бал скорочується до двох знаків після коми та не округляється знову. Так, наприклад...

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

Це є вирішальним для класифікації: \(2{,}3366\ldots\) не стає \(2{,}34\) , а \(2{,}33\) , і тому все ще достатньо для початкової школи.

Початковий запис ілюструє раннє округлення з припущеними середніми значеннями для кожного предмета \(1{,}6\) , \(2{,}6\) та \(2{,}6\) . З них спочатку виводяться цілі оцінки \(2\) , \(3\) та \(3\) . Їхнє середнє значення дорівнює

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

що означає, що учень не має права на пряме зарахування до початкової школи. Однак, без округлення до цілих оцінок, результат у гіпотетичному прикладі буде таким...

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

У другому прикладі округлення працює у протилежному напрямку: \(2{,}4\) , \(3{,}4\) та \(2{,}4\) стають цілими значеннями нот \(2\) , \(3\) та \(2\) , офіційно \(2{,}33\) . Однак неокруглені значення призводять до \(2{,}73\) . Приклади чітко демонструють ефект. Однак вони ще не показують, як часто це відбувається або якими будуть наслідки іншого методу округлення.

Тому для мого розрахунку я використовую чіткий простір результатів. Кожне середнє значення суб'єкта може бути одним із значень \(501\) у ньому.

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

Припустимо. Я однаково зважую всі впорядковані комбінації німецької мови, математики, а також місцевих і загальних дисциплін. Таким чином, існують

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

Випадки. Таким чином, модель однозначна, але штучна: вона припускає рівномірно розподілені середні показники предметів, незалежність трьох предметів та кроки рівно в одну соту. Вона не відображає фактичного розподілу дітей початкової школи Баварії.

Для трьох суб'єктних середніх \(d,m,h\) ми пишемо

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

для загального середнього значення, скороченого до двох знаків після коми. Тепер порівняємо три методи розрахунку.:

\[
\begin{вирівняно}
A_0 &= A(\operatorname{round}(d),\operatorname{round}(m),\operatorname{round}(h)),\\
A_1 &= A(\оператор{округлення}1(d),\оператор{округлення}1(m),\оператор{округлення}1(h)),\\
A_\mathrm{посилання} &= A(d,m,h).
\end{вирівняно}
\]

\(A_0\) відповідає розрахунку з використанням цілих оцінок, \(A_1\) – пропозиції з одним десятковим знаком, а \(A_\mathrm{ref}\) – неокругленому посиланню в моделі. Розрахунок можна реалізувати безпосередньо, наприклад, у 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
        );
    }
}

Невеликий допуск у calculate_average запобігає такому значенню, як \(2{,}67\) через його двійкове представлення у вигляді числа з плаваючою комою його помилково вважали \(2{,}669999\ldots\) обрізається. normalize_grade Крім того, це зводить кожне значення циклу назад до сітки сотого порядку. Існують щонайменше два різних можливих середніх значення. \(1/300\) окремо; толерантність \(10^{-9}\) тому достатньо малий, щоб не змінити жодного реального граничного випадку.

Програма компілюється та запускається з

rustc -O calc.rs && ./calc

Програма перебирає всі комбінації \(125\,751\,501\) та повертає результат:

ПорівнянняПорція
Цілі оцінки проти неокруглених середніх значень за предметами\(10{,}4411\,\%\)
Цілі оцінки порівняно з пропозицією з одним десятковим знаком\(10{,}1521\,\%\)
Пропозиція з одним знаком після коми порівняно з неокругленими середніми значеннями експертів\(0{,}6615\,\%\)

Центральна цінність для мене — це \(10{,}4411\,\%\): У більш ніж одній з десяти комбінацій раннє округлення до цілих класів призводить до іншого розрахованого типу школи, ніж неокруглене посилання. Ця пропорція описує виключно ефект округлення в межах обраної моделі.

Перехід до експертних середніх значень з одним знаком після коми призвів би до іншої класифікації у \(10{,}1521\,\%\) усіх модельних випадків порівняно з попереднім методом. Однак третє порівняння є вирішальним: порівняно з неокругленим орієнтиром, метод з одним знаком після коми залишає лише \(0{,}6615\,\%\) випадків відхилення. Таким чином, відхилення від орієнтира зменшується на

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

Для мене саме це і є сумнівним наслідком поточного методу розрахунку: передбачувані досягнення з конкретних предметів залишаються незмінними; лише момент часу, коли відбувається округлення, може змінити розрахований тип школи. Хоча розрахунок з одним десятковим знаком не повністю усуває цей ефект, він значно зменшує його в рамках моделі.

Однак ці цифри не показують, скільки дітей насправді постраждали. Оцінки в табелях успішності не обов'язково формуються як механічно округлені середні значення, академічна успішність не розподілена рівномірно і не є незалежною, а фактичний вибір типу школи не залежить виключно від цих трьох цифр. Мій розрахунок відповідає на більш конкретне питання: як часто округлення змінює розраховану оцінку, коли всі комбінації сотих значень однаково ймовірні?

Нарешті, порівняння з оригінальним дописом: загальний показник, згаданий там, приблизно \(10\,\%\) близький до моїх \(10{,}4411\,\%\) . Однак мої розрахунки не підтверджують чотири окремі випадки, кожен з яких позначено як \(1/6 \approx 17\,\%\) Для «пропущеної середньої школи з \(3{,}00\) », «пропущеної граматичної школи з \(2{,}33\) », «досягнутої граматичної школи з \(2{,}66\) » та «досягнутої середньої школи з \(2{,}66\) \(1{,}4615\,\%\) \(59{,}6096\,\%\) \(1{,}2023\,\%\) \(62{,}9395\,\%\) .

Чотири значення – це умовні ймовірності з референтними групами різного розміру. Без по-різному визначеного простору вибірки \(1/6\) неможливо вивести з них. Таким чином, мій розрахунок підтверджує ефект округлення, але не ці індивідуальні ймовірності. У будь-якому випадку, твердження про фактичну кількість уражених дітей вимагатимуть реальних розподілів оцінок та їх залежностей.

Назад