Форум программистов, компьютерный форум, киберфорум
C (Си)
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
1 / 1 / 0
Регистрация: 17.11.2018
Сообщений: 40
1

Ошибка вывода при использовании типа double

06.12.2020, 23:49. Просмотров 1709. Ответов 3

Здравствуйте. Написал программу решения нелинейного уравнения комбинированным методом хорд-касательных - она в двух версиях: в первой все вычисления производятся с использованием типа double, а во второй - long double. Компилировал обе версии с помощью одного и того же компилятора mingw, предустановленного в Code::Blocks 17.12. В случае с типом long double я получаю ответ с точностью до 31-го знака после запятой (Рисунок 1). Когда же я попытался запустить вторую версию (double, вычисления до 15-ти знаков после запятой), то получил на выходе -1,#IND000000 (Рисунок 2), а когда попробовал прописать команду #define __USE_MINGW_ANSI_STDIO 1 для неё же, то получил просто какой-то длинный набор цифр (Рисунок 3). И ещё один момент, который бросается в глаза, - количество итераций: хоть там и стоит ограничение в 1024 шага, но всё равно оно выполняется на один шаг больше; я также пробовал ставить ограничение до 1.000.000 шагов - даже в этом случае оно перевыполнялось на одни шаг. Объясните, пожалуйста, почему так получается.

Код программ:

1. тип long double:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#define __USE_MINGW_ANSI_STDIO 1
 
#include <locale.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
 
//  Исходная функция
 
long double f (long double x) {
    return ((x / (1.0 + pow(x, 4.0))) - log(x));
}
 
//  Первая производная
 
long double df1 (long double x) {
    return (((1.0 - 3.0 * pow(x, 4.0)) / pow((1.0 + pow(x, 4.0)), 2.0)) - 1.0 / x);
}
 
//  Вторая производная
 
long double df2 (long double x) {
    return (((((-12.0) * pow(x, 3.0)) * pow((1.0 + pow(x, 4.0)), 2.0) - (8.0 * pow(x, 3.0)) * (1.0 + pow(x, 4.0)) * 1.0 - 3 * pow(x, 4.0)) / pow((1.0 + pow(x, 4.0)), 4.0)) + (1.0 / pow(x, 2.0)));
}
 
//  Метод хорд
 
long double chordMethod (long double xChordMethod,
                         long double xTangentMethod) {
    return (xChordMethod - (f (xChordMethod)) / (f (xTangentMethod) - f (xChordMethod)) * (xTangentMethod - xChordMethod));
}
 
//  Метод касательных
 
long double tangentMethod (long double xChordMethod,
                           long double xTangentMethod) {
    return xTangentMethod - (f (xTangentMethod)) / (df1(xTangentMethod));
}
 
//  Метод хорд-касательных
 
void chordTangentMethod (long double leftBorder,
                         long double rightBorder,
                         long double epsilon) {
    long double xChordMethod,
                xTangentMethod,
                x;
 
    unsigned int presenceOfRoot = 1,
                 numberOfIterations = 0;
 
    if ((df1 (leftBorder) * df1 (rightBorder) < 0) || (df2 (leftBorder) * df2 (rightBorder) < 0)) {
        presenceOfRoot = 0;
    }
    else if (f (leftBorder) * df2 (leftBorder) > 0) {
        xTangentMethod = leftBorder;
        xChordMethod = rightBorder;
    }
    else {
        xTangentMethod = rightBorder;
        xChordMethod = leftBorder;
    }
 
    if (presenceOfRoot != 0) {
        while ((fabsl (xTangentMethod - xChordMethod) >= epsilon) && (numberOfIterations <= 1024)) {
            xTangentMethod = tangentMethod (xChordMethod, xTangentMethod);
            xChordMethod = chordMethod (xChordMethod, xTangentMethod);
            x = (xTangentMethod + xChordMethod) / 2.0;
 
            numberOfIterations++;
        }
 
        printf ("--Метод хорд-касательных--Вычисление с двойной точностью--\n\n");
 
        printf ("Корень уравнения: %.31Lf\n", x);
        printf ("Количество итераций: %u\n", numberOfIterations);
        printf ("Проверка решения: %.31Lf", f (x));
    }
    else {
        printf ("Интервал не содержит корень");
    }
}
 
int main () {
    setlocale (LC_ALL, "Russian");
 
    const long double epsilon = 1.0e-32;
          long double leftBorder = 1.36011,
                      rightBorder = 1.36012;
 
    chordTangentMethod (leftBorder, rightBorder, epsilon);
}
2. тип double:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//#define __USE_MINGW_ANSI_STDIO 1
 
#include <locale.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
 
//  Исходная функция
 
double f (double x) {
    return ((x / (1.0 + pow(x, 4.0))) - log(x));
}
 
//  Первая производная
 
double df1 (double x) {
    return (((1.0 - 3.0 * pow(x, 4.0)) / pow((1.0 + pow(x, 4.0)), 2.0)) - 1.0 / x);
}
 
//  Вторая производная
 
double df2 (double x) {
    return (((((-12.0) * pow(x, 3.0)) * pow((1.0 + pow(x, 4.0)), 2.0) - (8.0 * pow(x, 3.0)) * (1.0 + pow(x, 4.0)) * 1.0 - 3 * pow(x, 4.0)) / pow((1.0 + pow(x, 4.0)), 4.0)) + (1.0 / pow(x, 2.0)));
}
 
//  Метод хорд
 
double chordMethod (double xChordMethod,
                    double xTangentMethod) {
    return (xChordMethod - (f (xChordMethod)) / (f (xTangentMethod) - f (xChordMethod)) * (xTangentMethod - xChordMethod));
}
 
//  Метод касательных
 
double tangentMethod (double xChordMethod,
                      double xTangentMethod) {
    return xTangentMethod - (f (xTangentMethod)) / (df1(xTangentMethod));
}
 
//  Метод хорд-касательных
 
void chordTangentMethod (double leftBorder,
                         double rightBorder,
                         double epsilon) {
    double xChordMethod,
           xTangentMethod,
           x;
 
    unsigned int presenceOfRoot = 1,
                 numberOfIterations = 0;
 
    if ((df1 (leftBorder) * df1 (rightBorder) < 0) || (df2 (leftBorder) * df2 (rightBorder) < 0)) {
        presenceOfRoot = 0;
    }
    else if (f (leftBorder) * df2 (leftBorder) > 0) {
        xTangentMethod = leftBorder;
        xChordMethod = rightBorder;
    }
    else {
        xTangentMethod = rightBorder;
        xChordMethod = leftBorder;
    }
 
    if (presenceOfRoot != 0) {
        while ((fabs (xTangentMethod - xChordMethod) >= epsilon) && (numberOfIterations <= 1024)) {
            xTangentMethod = tangentMethod (xChordMethod, xTangentMethod);
            xChordMethod = chordMethod (xChordMethod, xTangentMethod);
            x = (xTangentMethod + xChordMethod) / 2.0;
 
            numberOfIterations++;
        }
 
        printf ("--Метод хорд-касательных--\n\n");
 
        printf ("Корень уравнения: %.15lf\n", x);
        printf ("Количество итераций: %u\n", numberOfIterations);
        printf ("Проверка решения: %.15lf", f (x));
    }
    else {
        printf ("Интервал не содержит корень");
    }
}
 
int main () {
    setlocale (LC_ALL, "Russian");
 
    const double epsilon = 1.0e-16;
          double leftBorder = 1.36011,
                 rightBorder = 1.36012;
 
    chordTangentMethod (leftBorder, rightBorder, epsilon);
}
0
Миниатюры
Ошибка вывода при использовании типа double   Ошибка вывода при использовании типа double   Ошибка вывода при использовании типа double  

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.12.2020, 23:49
Ответы с готовыми решениями:

Какой спецификатор использовать для корректного вывода типа данных double и long double
Подскажите пожалуйста, какой спецификатор использовать для корректного вывода типа данных double и...

Ошибка вывода значения 0 типа double
При выполнении этого кода при значении x=0 не выводится четкий ноль. Почему? Я так понимаю нужно...

Изменить программу вывода функции так, чтобы можно было передавать функции типа double(double,double)
Изменить программу вывода функции так, чтобы можно было передавать функции типа...

Ошибка округления при использовании float или double
Да-да, избитая тема. Понятно, что любое нецелое число может быть представленно в современных...

3
170 / 130 / 51
Регистрация: 18.07.2017
Сообщений: 682
07.12.2020, 15:34 2
Цитата Сообщение от PC_user1 Посмотреть сообщение
оно перевыполнялось на одни шаг
Отсчет с 0 идет, а не с 1
C++
1
(numberOfIterations <= 1024)
0
1 / 1 / 0
Регистрация: 17.11.2018
Сообщений: 40
07.12.2020, 16:53  [ТС] 3
Цитата Сообщение от assemberist Посмотреть сообщение
Отсчет с 0 идет, а не с 1
Понятно. Но как, всё-таки, можно объяснить получение в выводе -1,#IND000000 для double? Может ли быть тому причиной нехватка памяти для записи числа, так как в процессе вычислений дробная часть состоит из чисел, следующих после знака, стоящего на том же месте, что и порядок точности. Т. е. : 1,23456789123456789... при e = 0,000001; то есть выделенная часть не позволяет дальше работать с числом, так как в процессе вычислений мы как бы "входим" на территорию типа long double?
0
170 / 130 / 51
Регистрация: 18.07.2017
Сообщений: 682
07.12.2020, 17:03 4
Цитата Сообщение от PC_user1 Посмотреть сообщение
бъяснить получение в выводе -1,#IND000000
https://habr.com/ru/post/171203/
Возможно где-то на 0 поделил или взял от него логарифм. Короче говоря у тебя где-то выполняется недопустимая операция.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.12.2020, 17:03

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Ошибка при использовании vector (в конце, после вывода результатов выскакивает ошибка, но сам результат коректен)
Суть в следующем, мы считываем введеные значения и выводим этот массив Проблема такова что...

Ошибка при использовании типа ifstream
Заголовочный файл &quot;user.h&quot; #pragma once class User { public: void Read(ifstream&amp; data); };...

Ошибка при использовании IEnumerable<T>: Использование универсального типа IEnumerable требует аргумент типа 1
Доброго Вам времени суток. Помогите решить следующую задачку. На строке IEnumerable&lt;Device&gt; =...

Ошибка при использовании перегруженного оператора вывода в поток: no match for 'operator<<'
Пытаюсь написать класс комплексных чисел, но не могу сделать вот что: #include &lt;iostream&gt;...

Ошибка при преобразование типа строки из консоли в double
Есть переменная типа double, ввожу её значение с консоли, сразу же выбивает ошибку. Как правильно...

Ошибка при передаче свойства типа double с View в контроллер
Столкнулся с проблемой передачи типа decimal. Когда контроллер получает модель в Price всегда 0....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.