Очно-дистанційні курси інформатиків

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Очно-дистанційні курси інформатиків » Навчальний посібник » Проект "Перевірялка для квадратних рівнянь"


Проект "Перевірялка для квадратних рівнянь"

Сообщений 1 страница 9 из 9

1

Проект знову підняв проблему похибки обчислень. Ось текст ядра програми (з дійсними коефіцієнтами рівняння):

    void Button1Click(object sender, EventArgs e)
    {
    double a,b,c,x1,x2;
    try
    {
        a=double.Parse (A.Text);
        b=double.Parse (B.Text);
        c=double.Parse (C.Text);
        x1=double.Parse (X1.Text);
        x2=double.Parse (X2.Text);
       
        if (a*x1*x1+b*x1+c==0) R1.Text = "ПРАВИЛЬНО";
        else R1.Text = "НЕПРАВИЛЬНО";
       
        if (a*x2*x2+b*x2+c==0) R2.Text = "ПРАВИЛЬНО";
        else R2.Text = "НЕПРАВИЛЬНО";
       
        A.Enabled=B.Enabled=C.Enabled=X1.Enabled=X2.Enabled=false;
    }
    catch
    {
       
    }
    }
Рівняння з коефіцієнтами  25; -70; 13 має корені 0,2 і 2,6. Програма з цим погоджується. При коефіцієнтах 2,5; -7; 1,3  - корені, звичайно, такі ж самі. Але другий з них програм "забраковує". Як "правильно" писати програми для обчислень з дійсними числами?

0

2

Пилипчук О.П. написал(а):

Рівняння з коефіцієнтами  25; -70; 13 має корені 0,2 і 2,6. Програма з цим погоджується. При коефіцієнтах 2,5; -7; 1,3  - корені, звичайно, такі ж самі. Але другий з них програм "забраковує". Як "правильно" писати програми для обчислень з дійсними числами?

Зі слова "правильно" лапки можна забрати.

Дійсні числа як правило порівнюють з обмеженою точність. Абсолютна рівність дійсних чисел зазвичай не розглядається. Порівняння можна виконати так:  if (Math.Abs(a * x1 * x1 + b * x1 + c) < 0.000001).

Але в даному випадку я рекомендую написати так:

Код:
                double d = b * b - 4 * a * c;
                double X1 = (-b - Math.Sqrt(d)) / (2 * a);
                double X2 = (-b + Math.Sqrt(d)) / (2 * a);

                if (Math.Abs(X1 - x1) < 0.000001) R1.Text = "ПРАВИЛЬНО";
                else R1.Text = "НЕПРАВИЛЬНО";

                if (Math.Abs(X2 - x2) < 0.000001) R2.Text = "ПРАВИЛЬНО";
                else R2.Text = "НЕПРАВИЛЬНО";

0

3

Доречі для "точних" розрахунків можна користуватися типом decimal. В ньому застосовано ряд заходів для боротьби з помилками округлення. Разом з тим використання цього типу має певні незручності. Він здебільшого застосовується для банківських розрахунків.

0

4

Дійсні числа (float, double) зберігаються в двійковій системі (з двійковою експонентою!). Це має ряд наслідків. Щонайменше слід пам'ятати, що ці числа є лише наближенням десяткових чисел. Щоб не писати дуже багато, наведу цитату з MSDN:

ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/T_System_Double.htm

Remember that a floating-point number can only approximate a decimal number, and that the precision of a floating-point number determines how accurately that number approximates a decimal number. By default, a Double value contains 15 decimal digits of precision, although a maximum of 17 digits is maintained internally. The precision of a floating-point number has several consequences:

Two floating-point numbers that appear equal for a particular precision might not compare equal because their least significant digits are different.

A mathematical or comparison operation that uses a floating-point number might not yield the same result if a decimal number is used because the floating-point number might not exactly approximate the decimal number.

A value might not roundtrip if a floating-point number is involved. A value is said to roundtrip if an operation converts an original floating-point number to another form, an inverse operation transforms the converted form back to a floating-point number, and the final floating-point number is equal to the original floating-point number. The roundtrip might fail because one or more least significant digits are lost or changed in a conversion.

0

5

А також http://en.wikipedia.org/wiki/IEEE_float … t_standard

На жаль ця стаття ввікіпедії не перекладена ні на українську, ні на російську мову.

0

6

Кухар Андрій написал(а):

Але в даному випадку я рекомендую написати так:

Дякую!

0

7

Щодо останнього проекту ОП. Навіщо так ускладнювати собі життя: попередня перевірялка - просто і класно. Зараз ми влізли у проблеми роботи з дійсними числами і це нам дуже цікаво. А дітям так буде?

Отредактировано Vitaly (2007-11-18 17:24:20)

0

8

Є й інша точка зору. Проблема обчислень з дійсними числами важлива для програміста. Чому б не використати цей приклад для того, щоб ознайомити учнів з нею та з можливими шляхами її розв'язання? Програма досить проста, знайшовся підходящий набір даних, при якому проблема "проявилась". Залишилось написати кілька рядків пояснення...

0

9

Загалом проблема з точністю закладена в саму постановку цієї задачі, навіть якби обчислення проводилися абсолютно точно. Розв'язки квадратного рівняння можуть бути іраціональними. І немає ніякої можливості ввести точну відповідь у вигляді десяткового дробу. Наприклад для рівняння x*x - 2 = 0. Тому потрібно порівнювати відповідь з обмеженою точністю. Достатньо буде обмежитися 3-4 значущими цифрами. Інакше просто неможливо буде перевірити розв'язок такого рівняння.

0


Вы здесь » Очно-дистанційні курси інформатиків » Навчальний посібник » Проект "Перевірялка для квадратних рівнянь"