Построить график функции с помощью символов
Нужно нарисовать график функции в консоли на С++, но проблема в том, что нельзя использовать библиотеки для работы с графикой. То есть нарисовать её нужно с помощью символов (*) и цикла, а я не понимаю, как это сделать.Вот сама функция exp(x-2)-5*x^2+3
#include #include #include double foo(const double x) < return exp(x-2)-5*x*x+3; >int main() < SetConsoleCP(1251); SetConsoleOutputCP(1251); int x,a,b,t; while (true) < std::cout > a; std::cin >> b; if (a > b) < std::cout b" else < break; >> while (true) < std::cout > t; if (t <=0) < >else < break; >> for (int i = a; i >
Получилось только ось нарисовать. Функция может возвращать как положительные так и отрицательные значения.
Отслеживать
задан 20 мая 2020 в 7:58
1 1 1 серебряный знак 1 1 бронзовый знак
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
примерно так. Но под вашу функцию надо оси масштабировать. этим займитесь сами В общем и целом подход такой — график «рисуется» в двумерном массиве и потом выводится.
// размеры "экрана" // по оси абсцисс #define scene_length 150 // по оси ординат #define scene_width 40 char scene[scene_length][scene_width*2]; // тут будем график рисовать. по оси ординат делаем в 2 раза больше (под отрицательные значения) for(int x=0;x // тут будем обсчитывать функцию и рисовать график for(int x=0;x // выводим на экран for(int y=scene_width*2-1;y>=0;y--) < printf ("%03d ", y-scene_width); for(int x=0;xprintf("\n"); > return 0;
Построение функций в консоли. Часть 2 (График)

В прошлый раз я остановился на построении таблицы значения функций. Пришла пора перейти к построению самого графика, ради чего все это, собственно, и начиналось.
Итак, основная идея состоит в следующем. Повернем координатную ось на 90 градусов по часовой стрелке. Это нужно для того, чтобы упростить построения, не храня данные о каждой точке в каком-нибудь листе.
Дальше ограничиваем координатную ось игрек 82 символами для лучшей читабельности графика. Понятно, что при этом мы теряем точность и график будет больше схематическим (слишком сжатым), особенно для «крутых» функций, но все же.
После этого мы высчитываем положение оси x относительно оси игрек, то есть ищем, в каком месте у нас будет точка (x, 0). Ну а потом построчно будем ставить в соответствие x значение функции y1 в этой точке.
Поехали
Для начала нам понадобится следующая формула:
Самому графику мы отведем 80 позиций, два оставшихся места будут чисто декоративными. Этой формулой мы находим, какой диапазон значений соответствует одной позиции в нашем графике. Тогда мы сможем правильно отметить на нем текущую точку.
Основные идеи обозначены, поэтому перейдем к самому коду
dial_length = 12 label = "График функции y1 = x**3 - 2*x**2 + 4*x - 8" print(">".format(len(label) + dial_length, label), '\n') print(">\n >>\n".format(aux = [dial_length + 82, 'y' , 82*'-']));
В том числе и благодаря комментариям к первой части, я узнал о такой штуке, как format. Мне она показалась действительно удобнее моих танцев с бубном, поэтому огромный кусок кода с вычисления отступов превратился в пару строк
print(">".format(len(label) + dial_length, label), '\n')
Единичка отвечает за номер элемента, переданного в качестве аргумента функции format, то есть это «ссылка» (не в буквальном смысле) на переменную label, которую мы собственно выводим на экран. Нумерация идет точно так же, как и в листах — с нуля.
Пара символов :> используется для того, чтобы выровнять выводимый на экран текст по правой стороне. Ну а после символа > нужен для того, чтобы определить то количество позиций строки, которое вам нужно.
То есть в данном случае мы резервируем для строки label len(label) + dial_length позиций, причем сам label занимает только len(label), и выравниваем внутри совокупности этих позиций текст по правой стороне.
print(">".format(len(label) + dial_length, label), '\n') print(dial_length*' ' + label, '\n')
эти строки эквивалентны
Да, для строк, наверное, проще использовать второй вариант, но применить первый для общего развития не помешает)
print(">\n >>\n".format(aux = [dial_length + 82, 'y' , 82*'-']));
В format можно запихивать даже массивы типа r_value (в C++), то есть созданные непосредственно при передаче аргумента.
Зафиксируем переменные, которые у нас постоянны, то есть они не зависят от текущего значения функции.
В питоне нет условного const для обозначения констант, поэтому принято называть такие переменные заглавными буквами и просто их не изменять.
MAX_Y1_VALUE_DIFFERENCE = (max_y1_value - min_y1_value) + \ (max_y1_value == min_y1_value) RATIO = MAX_Y1_VALUE_DIFFERENCE / 80 AXIS_X_POS = abs(int((- min_y1_value) / RATIO)) if (AXIS_X_POS > 80): AXIS_X_POS = 81
Так как RATIO по понятным причинам не может быть равно 0, MAX_Y1_VALUE_DIFFERENCE должно быть положительным числом. Именно для этого в правой части присваивания есть второе слагаемое.
Позицию оси икс мы высчитываем по формуле
Откуда берется эта формула? Мы просто высчитываем отношение отрезков (на оси игрек) от начала оси (min(y1)) до текущего значения функции (y1(x)) и отрезка от начала оси до ее конца (max(y1)). Ну и умножаем это отношение на 80, чтобы найти такое расстояние от начала оси до текущего значения в пробелах (поэтому можно использовать только целые числа), которое отразит отношение-формулу на графике.
Так как нас интересует позиция при y1(x) = 0, то подставляем в формулу необходимые значения и вуаля.
Теперь можно переходить непосредственно к печати значений
while (is_sequence_decreasing and from_x >= to_x) or \ (not is_sequence_decreasing and from_x
Цикл нам уже знаком. Придется второй раз посчитать каждое значение функции, чтобы не хранить их в листе или чём-то еще.
Позицию игрека вычисляем по выше приведенной формуле.
Верхнюю разность из формулы нам придется еще пофиксить, предусмотрев случай, когда в формуле будет получаться неопределенность вида ноль на ноль. Если такая неопределенность возникнет, то она будет означать, что текущее значение y1(x) = max(y1), а значит текущее значение игрека совпадет с концом оси y.
print(".6g>".format(dial_length, from_x), end='') if (negative_value_exists): if y1_cur_value = 0 + RATIO / 2: req_aux = pos_of_y - AXIS_X_POS if (req_aux != 0): print(AXIS_X_POS * ' ' + '|' + (req_aux - 1) * ' ' + '*') else: print((AXIS_X_POS) * ' ' + '|*') else: print(AXIS_X_POS * ' ' + '*') else: print('|' + pos_of_y* ' ' + '*') AXIS_X_POS = 0 from_x += pace_x print((dial_length + AXIS_X_POS) * ' ' + '|\n', (dial_length + AXIS_X_POS - 3) * ' ' + 'x V')
Эта часть кода непосредственно отвечает за печать самого графика
print(".6g>".format(dial_length, from_x), end='')
Здесь-таки format очень сильно пригодился и упростил код. ^ позволяет нам выровнять число по центру выделенной области (в данном случае, 12 позиций). g отвечает за числа — если у них нет дробной части, то печататься она и не будет (число как int), иначе — 6 знаков после запятой
Так как наш график ограничен пространством в 80 символов вдоль оси y, на нашем графике значение функции в точке будет совпадать с осью x не только в случае y1(x) = 0, но и в окрестности [0 — RATIO/2, 0 + RATIO/2].
Всего у нас есть три случая расположения звездочки (то есть точки) и вертикальной палки (то есть оси x): '*|' (y1(x) = 0 + RATIO/2), эти три случая и будем рассматривать.
- y1(x) В этом случае точка находится до оси x, поэтому мы ищем расстояние от точки до оси в пробелах. Из-за округления чисел может получится так, что значения переменных AXIS_X_POS и pos_of_y могут совпасть. Но такого быть не может, так как в этом случае мы бы попали в третий случай. У нас же точка не совпадает с осью х, поэтому необходимо дополнительное условие, которое будет уменьшать на 1 переменную pos_of_y в случае равенства.
- y(x) >= 0 + RATIO/2
Случай идентичен первому случаю, только точка будет расположена с другой стороны от оси х и все вышеописанные действия под это корректируются - остальное
Самый простой случай — просто печатаем звездочку на месте оси
Ну и завершаем программу дорисовкой оси x.
Итак, код, который в итоге получился:
dial_length = 12 label = "График функции y1 = x**3 - 2*x**2 + 4*x - 8" print(".6f>".format(dial_length, x_copy)) print(">".format(len(label) + dial_length, label), '\n') print(">\n >>\n".format(aux = [dial_length + 81, 'y' , 82*'-']), end=''); MAX_Y1_VALUE_DIFFERENCE = (max_y1_value - min_y1_value) + \ (max_y1_value == min_y1_value) RATIO = MAX_Y1_VALUE_DIFFERENCE / 80 AXIS_X_POS = abs(int((- min_y1_value) / RATIO)) if (AXIS_X_POS > 80): AXIS_X_POS = 81 while (is_sequence_decreasing and from_x >= to_x) or \ (not is_sequence_decreasing and from_x <= to_x): y1_cur_value = y1(from_x) cur_y1_value_and_min_difference = (y1_cur_value - min_y1_value) + \ (y1_cur_value == min_y1_value) * \ ((max_y1_value == min_y1_value)) pos_of_y = int(cur_y1_value_and_min_difference * 80 / \ MAX_Y1_VALUE_DIFFERENCE) print(".6g>".format(dial_length, from_x), end='') if (negative_value_exists): if y1_cur_value = 0 + RATIO / 2: req_aux = pos_of_y - AXIS_X_POS if (req_aux != 0): print(AXIS_X_POS * ' ' + '|' + (req_aux - 1) * ' ' + '*') else: print((AXIS_X_POS) * ' ' + '|*') else: print(AXIS_X_POS * ' ' + '*') else: print('|' + pos_of_y* ' ' + '*') AXIS_X_POS = 0 from_x += pace_x print((dial_length + AXIS_X_POS) * ' ' + '|\n', (dial_length + AXIS_X_POS - 3) * ' ' + 'x V')
Запустим программу на нескольких тестах
Программа на си для построения графика функции
В этой статье мы разберем программу на языке программирования си для построения графиков функций. В нашей программе будут отражаться система координат с делениями и подписями на них и будут строиться графики двух функций, который может сам задать пользователь.
В программе на си для построения графика функции вводятся следующие константы
X0 , Y0 - координаты центра координат
k – масштаб одного деления на осях (сколько пикселов в одном делении)
Опишем все функции и процедуры используемые в программе для построения графиков функций
Подробно о задании функций и процедур в си
int osx (float x) переводит реальную координату на оси ox в координату экрана
int osy (float y) переводит реальную координату на оси oy в координату экрана
float F1 ( float x ) и float F2 ( float x ) задают функции , графики которых мы будем строить
void Point ( float x, float y, int color ) рисует точку графика функции на экране
Перед построением графиков функций необходимо построить систему координат. Для построения системы координат используется процедура
void Axes()
В этой процедуре в цикле for рисуются линии меток делений на равном расстоянии друг от друга, который определяется масштабом одного деления k и выводятся значения делений с помощью двух операторов
sprintf ( s, "%d", i ); // записываем в строковую переменную число деления
outtextxy ( xe-10, Y0+4, s ); // вывод числа
Процедура grafik1() и grafik2() строят графики функций f1 и f2
В этих процедурах в цикле for для всех доступных значений x определяется координата y и точка графика строится с помощью процедуры point()
Пример работы программы построения графиков на си, функции пользователь может менять

Программа на си для построения графиков функций
#include
#include //графический режим
#include // математические функции
//------------------------------------------------
const int X0 = 100, Y0 = 400;// координаты центра координат
const float k = 15;// масштаб в точках одного деления на графике
//-----------------------------------------
// перевод y в координаты экрана
//-----------------------------------------
int osx (float x)
return X0+k*x;
>
//-----------------------------------------
//перевод y в координаты экрана
//-----------------------------------------
int osy (float y)
return Y0-k*y;
>
// первая функция
float F1 ( float x )
return sqrt(2*x);
>
// вторая функция
float F2 ( float x )
return x*x/2;
>
// построение осей
void Axes()
int i, xe,ye,y1;
char s[10];
line ( X0, 0, X0, 599 ); // ось ox
line ( 0, Y0, 799, Y0 ); // ось oy
// метки на оси ox
for ( i = 1; i xe = osx ( i );
line ( xe, Y0-2, xe, Y0+2 ); // рисуем деление разметки
sprintf ( s, "%d", i ); // записываем в строковую переменную число деления
outtextxy ( xe-10, Y0+4, s ); // вывод числа
>
// метки на оси oy
for ( i = 1; i ye = osy( i+1 );
line ( X0-2, ye, X0+2, ye ); // рисуем деление
sprintf ( s, "%d",i ); // записываем в строковую переменную число деления
outtextxy ( X0+10, ye+4, s ); // вывод числа
>
>
// построение точки графика функции
void Point ( float x, float y, int color )
int xe, ye;
xe = osx(x);
ye = osy(y);
if ( xe >= 0 && xe < 800 && ye >= 0 && ye < 600 )
putpixel(xe, ye, color);
>
// построение графика первой функции
void grafik1()
float x, h, xmin, xmax;
h = 1 / k;
xmin = (-X0)/ k;
xmax=(800-X0)/k;
for ( x = xmin; x Point(x, F1(x), WHITE);
>
>
// построение графика второй функции
void grafik2()
float x, h, xmin, xmax;
h = 1 / k;
xmin = (-X0)/ k;
xmax=(800-X0)/k;
for ( x = xmin; x Point(x, F2(x), WHITE);
>
>
// главная программа
main ()
initwindow ( 800, 600 ); // создать окно для графики
Axes(); // построение и разметка осей координат
grafik1(); // строим график первой функции
grafik2(); // строим график второй функции
getch(); // ждать нажатия на клавишу
closegraph(); // закрыть окно для графики
>
Полезно почитать по теме построение графиков функций в программа си
Графика в си
Процедуры и функции в си
Комментарии ( 0 )
Нет комментариев. Ваш будет первым!
Построение графика функции
Разработать программу для построения графика функции у = 2*sinx*e^4/5 . Считать из файла х функции. График функции построить в интервале от -50 до 50. Результатом работы программы будут считаться два массива, которые содержат значения промежуточные значения x и y для интервала [-50; 50]. Возможно кто-то сможет построить график по этим значениям, это будет еще лучше.
К сожалению, решения данной задачи пока нет. Если Вы решили эту задачу, сообщите нам, и мы выложим её на сайте.
Следующие статьи помогут вам в решении данной задачи:
Дата: 13.01.2014
Поделиться:
Комментарии
Ihor Lokki
08.03.2015 Решение с использованием OpenGl:
#include #include #include #include #include #include int count = 0; // Размер масива У,Х float* X; // масив для хранение х-ов float* Y; // масив для хранения у-ов void display() < // Функция перерисовки дисплея glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_LINES); glColor3f(1.0, 0.0, 0.0); glVertex3f(0, 50, 0); // Рисование системи координат glVertex3f(0, -50, 0); glVertex3f(-50, 0, 0); glVertex3f(50, 0, 0); for(int i = -11; i < 8; i++)< glVertex3f(10 + i * 5, -2, 0); glVertex3f(10 + i * 5, 2, 0); >for(int i = -11; i < 8; i++)< glVertex3f(-2, 10 + i * 5, 0); glVertex3f(2, 10 + i * 5, 0); >// Конец рисования системы крдинат glEnd(); glBegin(GL_POINTS); // Рисование точок графика функции float y; for(int i = 0; i < count; i++)< glVertex3f(X[i], Y[i], 0); >glEnd(); glutSwapBuffers(); > int main(int argc, char** argv) < std::vectorarr; // Вектор в котором будем хранить даные из файла std::ifstream fin; // Для вивода даних из файла std::string path; // Путь к файлу do< // Цикл который обеспечывает открития файла std::cout>path; fin.open(path.c_str()); if(!fin.is_open()) < std::cout>while(!fin.is_open()); float i = 0.0; while(!fin.eof())< // Запись даних из файла в вектор fin>>i; arr.push_back(i); > fin.close(); for(int j = 0; j < arr.size(); j++)< // Цикл для подсчота х-ов в диапазоне if(arr[j] >-50.0 && arr[j] < 50.0) // [-50;50] < count++; >> X = new float[count]; // Создание масива с х Y = new float[count]; // Создание масива с У int n = 0; for(int j = 0; j < arr.size(); j++)< // Цыкл для записи даних(х) указаного if(arr[j] >-50.0 && arr[j] < 50.0)< // диапазона в масив Х X[n] = arr[j]; n++; >> for(int j = 0; j < count; j++)< Y[j] = 2*sin(X[j])*pow(M_E,4/5); // Заполнение масива У >// Стандартное создание окна в OpenGl glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(400, 400); glutInitWindowPosition(20, 810); glutCreateWindow("Rownanie"); glClearColor(0, 0, 0, 0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-55, 55, -55, 55, -100, 100); glutDisplayFunc(display); glutMainLoop(); delete [] X; delete [] Y; >
Sancho
Оставить комментарий
Вы должны войти, чтобы оставить комментарий.
Rust Journey: Хотите освоить язык программирования, который завоевывает мир?
Илон Маск, один из ведущих инноваторов нашего времени, утверждает, что за Rust будущее. А когда последний раз он ошибался в своих прогнозах?
✨ Не упустите свой шанс быть в авангарде IT-революции. Подписывайтесь на канал Rust Journey и начните свой путь в захватывающий мир Rust сегодня!