Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.10.2011, 00:07   #1
Prizrak86
Форумчанин
 
Аватар для Prizrak86
 
Регистрация: 15.10.2011
Сообщений: 139
Восклицание не правильная работа вычислительного процесса.

Исходные данные. xn=0.25 xk=0.8 dx= 0.05 a=1.75
Трассировал данные получал что(точка остановка на скобке конца тела цикла):
01 циклическая операция: xn=0.3
02 циклическая операция: xn=0.35
03 циклическая операция: xn=0.39999999999999997
04 циклическая операция: xn=0.44999999999999996
05 циклическая операция: xn=0.49999999999999994
06 циклическая операция: xn=0.54999999999999993
07 Циклическая операция: xn=0.6
08 циклическая операция: xn=0.65
09 циклическая операция: xn=0.70000000000000007
10 циклическая операция: xn=0.75000000000000011
11 циклическая операция: xn=0.80000000000000016
причем при выводе в консоль числа округлялись и выводились правильными, но из-за такой возникающей погрешности не выполняется последний раз цикл, когда xn==xk, это можно обойти конечно и округлением результата каждый раз при вычислении до 2-ух сотых, но это не приемлемо.

Вопрос в следующем: Почему возникает погрешность и как правильно поставить условие что бы универсально от неё избавиться?


Код:
double xn, xk, dx, a, y;
string S;
                        do
                        {
                            Console.Clear();
                            Console.Write("Введите начальное значение Х ");
                            S = Console.ReadLine();
                        }
                        while (double.TryParse(S, out xn) == false);

                        do
                        {
                            Console.Clear();
                            Console.Write("Введите конечное значение Х ");
                            S = Console.ReadLine();
                        }
                        while (double.TryParse(S, out xk) == false);

                        do
                        {
                            Console.Clear();
                            Console.Write("Введите приращение Х ");
                            S = Console.ReadLine();
                        }
                        while (double.TryParse(S, out dx) == false);

                        do
                        {
                            Console.Clear();
                            Console.Write("Введите a ");
                            S = Console.ReadLine();
                        }
                        while (double.TryParse(S, out a) == false);

                        if ((a * xn * Math.Sqrt(xn)) + Math.Pow(Math.E, -a * Math.Pow(Math.Cos(xn), 2)) >= 0 && xn >= 0)
                        {
                            while(xn<=xk)
                            {
                                y = Math.Sqrt((a * xn * Math.Sqrt(xn)) + Math.Pow(Math.E, -a * Math.Pow(Math.Cos(xn), 2)));
                                Console.WriteLine("При a={0} и при x={1} Y={2}", a, xn, y);
                                xn +=dx;
                            }//Точка останова (здесь выводятся значения переменной xn)
                        }
                        else
                        {
                            Console.WriteLine("Не выполнено условие области определеления функции.");
                        }
                        Console.ReadKey();
Программист это не профессия, программист - это образ жизни.
Prizrak86 вне форума Ответить с цитированием
Старый 22.10.2011, 01:51   #2
Lasur
Форумчанин
 
Аватар для Lasur
 
Регистрация: 13.10.2011
Сообщений: 143
По умолчанию

Скорее всего сбои получаются из-за неточностей представления дробных чисел в бинарном виде. Непонятно только почему на консоль число выводится в нужном виде.
Все имена, фамилии, ники, даты и события упоминаемые в моих постах, являются вымышленными. Все совпадения с реально существующими - случайны.
Lasur вне форума Ответить с цитированием
Старый 22.10.2011, 10:04   #3
Prizrak86
Форумчанин
 
Аватар для Prizrak86
 
Регистрация: 15.10.2011
Сообщений: 139
По умолчанию

Цитата:
Сообщение от Lasur Посмотреть сообщение
Скорее всего сбои получаются из-за неточностей представления дробных чисел в бинарном виде. Непонятно только почему на консоль число выводится в нужном виде.
никогда не слышал о возможности такого, двоичный код как десятеричный довольно четко описывают математические операции, разница в том что мы не привыкли к бинарной системе исчисления. но возможность существования такой проблемы возможно допустить.
Программист это не профессия, программист - это образ жизни.
Prizrak86 вне форума Ответить с цитированием
Старый 22.10.2011, 10:31   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
никогда не слышал о возможности такого, двоичный код как десятеричный довольно четко описывают математические операции, разница в том что мы не привыкли к бинарной системе исчисления. но возможность существования такой проблемы возможно допустить.
вообще то в принципе при работе с числами с плавующей запятой всегда есть погрешность.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 22.10.2011, 11:46   #5
Prizrak86
Форумчанин
 
Аватар для Prizrak86
 
Регистрация: 15.10.2011
Сообщений: 139
По умолчанию

остался вопрос: Как решить проблему не точного вычисления?
Программист это не профессия, программист - это образ жизни.
Prizrak86 вне форума Ответить с цитированием
Старый 22.10.2011, 13:13   #6
Скарам
Дружите с Linq ;)
Форумчанин
 
Аватар для Скарам
 
Регистрация: 15.10.2008
Сообщений: 822
По умолчанию

Код:
class Program
    {
        static void Main(string[] args)
        {
            double xn, xk, dx, a, y;
            string S;
            int pow;
            do
            {
                Console.Clear();
                Console.Write("Введите начальное значение Х ");
                S = Console.ReadLine();
            }
            while (double.TryParse(S, out xn) == false);

            do
            {
                Console.Clear();
                Console.Write("Введите конечное значение Х ");
                S = Console.ReadLine();
            }
            while (double.TryParse(S, out xk) == false);

            do
            {
                Console.Clear();
                Console.Write("Введите приращение Х ");
                S = Console.ReadLine();
            }
            while (double.TryParse(S, out dx) == false);

            do
            {
                Console.Clear();
                Console.Write("Введите a ");
                S = Console.ReadLine();
            }
            while (double.TryParse(S, out a) == false);

            pow = GetPow(dx);

            if ((a * xn * Math.Sqrt(xn)) + Math.Pow(Math.E, -a * Math.Pow(Math.Cos(xn), 2)) >= 0 && xn >= 0)
            {
                while (xn <= xk)
                {
                    y = Math.Sqrt((a * xn * Math.Sqrt(xn)) + Math.Pow(Math.E, -a * Math.Pow(Math.Cos(xn), 2)));
                    Console.WriteLine("При a={0} и при x={1} Y={2}", a, xn, y);
                    xn = Math.Round(xn, pow);
                }
            }
            else
            {
                Console.WriteLine("Не выполнено условие области определеления функции.");
            }
            Console.ReadKey();

        }
        public static int GetPow(double delta)
        {
            int pow = 0;
            do
            {
                pow++;
                delta *= 10;
            } 
            while (delta < 0);
            return pow + 2;
        }
Можно так.. просто обрезай погрешность ( цифры меньше дельты).
Не давай организму поблажки, каждый день тренируй его в шашки..
Скарам вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание программы вычислительного процесса с разветвлением C++ zpMirtzp Помощь студентам 1 10.05.2011 19:47
Правильная работа условия if Andruha10 PHP 1 22.08.2010 21:23
Не правильная работа for .. to Neptunium Общие вопросы Delphi 7 05.04.2010 00:32
ПРОГРАММИРОВАНИЕ РАЗВЕТВЛЯЮЩЕГОСЯ ВЫЧИСЛИТЕЛЬНОГО ПРОЦЕССА Rustem5 Помощь студентам 1 19.03.2010 18:16
Схемы вычислительного процесса Natali_11111 Помощь студентам 1 03.03.2010 18:53