ТОР 5 статей: Методические подходы к анализу финансового состояния предприятия Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века Характеристика шлифовальных кругов и ее маркировка Служебные части речи. Предлог. Союз. Частицы КАТЕГОРИИ:
|
Rational operator- (int a);// Умножение 2-х рациональных чисел Rational operator* (Rational a); // Умножение рационального числа на целое Rational operator* (int a); // Деление 2-х рациональных чисел Rational operator/ (Rational a); // Деление рационального числа на целое Rational operator/ (int a); // Печать рационального числа // Если знаменатель есть 1, число печатается как целое friend ostream &operator<< (ostream &stream, Rational &ob); // Ввод рационального числа // Допустиый формат: x, -x, x/y, -x/y friend istream &operator>> (istream &stream, Rational &ob);
// Извлечь целочисленный квадратный корень из рационального числа // Если корень равен 0, возвращается 0 // Если корень извлекается точно, возвращается 1, значение в x // Если корень не извлекается точно, возвращается 2, // извлеченное значение в x, инверсное подкоренное выражение в y int Sqrt (Rational &x, Rational &y); Для организации работы с системой векторов были использованы следующие типы данных: // Исходная система векторов Rational **a; // Ортогональная система векторов Rational **b; Программный код довольно подробно документирован и позволяет без особого труда разобраться в реализации процесса ортогонализации Грамма-Шмидта. Приведенные тесты показывают безошибочную работу программы. Список литературы 1. Генри Уоррен-мл.. Алгоритмические трюки для программистов. Издательство “Вильямс”, М. 2014 2. Г. Шилдт. Самоучитель C++. Издательство “BHV”, М. 1998 3.Курош А.Г. Курс высшей алгебры. Издательство “Лань”, К. 2004
Приложение
#include <stdio.h> #include <iostream> #include <stdlib.h> #include <conio.h> #include <stdio.h> #include <string> #include <windows.h>
using namespace std;
// Преобразование русского текста для корректной печати на консоль char txt[1000]; char *rus (const char *s) { CharToOem (s, txt); return txt; }
// Класс рациональных чисел class Rational {
public:
// Конструктор по умолчанию. // Создает рациональный 0 - пару (0/1) Rational (void) { m = 0; n = 1; }
// Конструктор создания рационального числа m/n, эквивалентного a/b, // но с взаимно несократимыми числителем и знаменателем. // Если b == 0, то считается, что это задано рациональный 0 - пара (0/1) Rational (int a, int b) { int d;
if (b == 0) { b = 1; a = 0; }
// Приведение знака if (b < 0) { b = -b; a = -a; }
// Приведение к несократимой дроби d = Nod (a, b); m = a / d; n = b / d; }
// Конструктор создания рационального числа m/n, эквивалентного a/1 Rational (int a) { m = a; n = 1; }
// Деструктор (ничего не делает) ~Rational () { }
// Получить значение числителя и знаменателя int GetM (void) { return m; }
int GetN (void) { return n; }
// Сложение 2-х рациональных чисел Rational operator+ (Rational a) { Rational t (m * a.n + n * a.m, n * a.n);
return t; }
// Сложение с присваиванием 2-х рациональных чисел Rational operator+= (Rational a) { Rational t (m * a.n + n * a.m, n * a.n);
return *this = t; }
// Сложение рационального числа и целого числа Rational operator+ (int a) { Rational t (m + n * a, n);
return t; }
// Вычитание 2-х рациональных чисел Rational operator- (Rational a) { Rational t (m * a.n - n * a.m, n * a.n);
return t; }
// Вычитание рационального числа и целого числа Rational operator- (int a) { Rational t (m - n * a, n);
return t; }
// Умножение 2-х рациональных чисел Rational operator* (Rational a) { Rational t (m * a.m, n * a.n);
return t; }
// Умножение рационального числа на целое Rational operator* (int a) { Rational t (m * a, n);
return t; }
// Деление 2-х рациональных чисел Rational operator/ (Rational a) { // Контроль деления на ноль if (a.m == 0) { cout << rus ("\nДеление на ноль!\nДля завершения работы нажмите любую клавишу..."); getch (); exit (1); }
Rational t (m * a.n, n * a.m);
return t; }
// Деление рационального числа на целое Rational operator/ (int a) { // Контроль деления на ноль if (a == 0) { cout << rus ("\nДеление на ноль!\nДля завершения работы нажмите любую клавишу..."); getch (); exit (1); }
Rational t (m, n * a);
return t; }
// Печать рационального числа // Если знаменатель есть 1, число печатается как целое friend ostream &operator<< (ostream &stream, Rational &ob) { if (ob.n == 1) stream << ob.m; else stream << ob.m << "/" << ob.n; return stream; }
// Ввод рационального числа // Допустиый формат: x, -x, x/y, -x/y friend istream &operator>> (istream &stream, Rational &ob) { string s; char *q, sign; int m, n;
for (;;) { cout << rus ("Введите число: ");
// Ввод символьного представления рационального числа stream >> s;
// Адрес начала строки q = (char *)s.c_str ();
if ((sign = *q) == '+' || sign == '-') ++q;
if (!isdigit (*q)) { cout << rus ("Число ошибочно\n"); continue; }
for (m = 0; isdigit (*q); ++q) m = m * 10 + *q - '0';
if (*q == 0) { n = 1; } else if (*q!= '/' ||!isdigit (*++q)) { cout << rus ("Число ошибочно\n"); continue; } else { for (n = 0; isdigit (*q); ++q) n = n * 10 + *q - '0'; if (*q || n == 0) { cout << rus ("Число ошибочно\n"); continue; } }
if (sign == '-') m = -m;
ob.m = m; ob.n = n; return stream; } }
// Извлечь целочисленный квадратный корень из рационального числа // Если корень равен 0, возвращается 0 // Если корень извлекается точно, возвращается 1, значение в x // Если корень не извлекается точно, возвращается 2, // извлеченное значение в x, инверсное подкоренное выражение в y int Sqrt (Rational &x, Rational &y) { int a, b;
if (m == 0) return 0;
a = Sqrt (m); b = Sqrt (n);
if (a * a == m && b * b == n) { x.m = a; x.n = b; return 1; }
if (a * a == m) { x.m = a; x.n = 1;
y.m = n; y.n = 1; return 2; }
if (b * b == n) { x.m = 1; x.n = b;
y.m = 1; y.n = m; return 2; }
x.m = x.n = 1; y.m = n; y.n = m; return 2; }
private:
// Числитель и знаменатель рациональной дроби int m, n;
// Метод Ньютона поиска целочисленного квадратного корня // Алгоритм заимствован из книги: // Генри Уоррен-мл., Алгоритмические трюки для программистов (стр. 307) // Издательский дом "Вильямс", 2014 int Sqrt (unsigned x) { unsigned x1; int s, gO, gl;
if (x <= 1) return x;
s = 1; x1 = x - 1;
if (x1 > 65535) { s += 8; x1 >>= 16; }
if (x1 > 255) { s += 4; x1 >>= 8; }
if (x1 > 15) { s += 2; x1 >>= 4; }
if (x1 > 3) { ++s; }
// gO = 2**s gO = 1 << s;
//gl = (gO + x / gO) / 2 gl = (gO + (x >> s)) >> 1;
// Повторяем, пока приближения строго уменьшаются while (gl < gO) { gO = gl; gl = (gO + (x / gO)) >> 1; }
return gO; }
// Вычисление наибольшего общего делителя чисел m,n int Nod (int m, int n) { int p;
m = abs (m); n = abs (n);
do { p = m % n; m = n; n = p; } while (n!= 0);
return m; } };
// Скалярное произведение двух рациональных массивов a и b размером n Rational Scalar (Rational *a, Rational *b, int n) { Rational s;
while (--n >= 0) { s += *a++ * *b++; }
return s; }
// Умножение рационального массива x размером n на // рациональное число v с получением результата y void Mul (Rational *y, Rational *x, Rational v, int n) { while (--n >= 0) { *y++ = *x++ * v; } }
// Вычитание из рационального массива x размером n // рационального массива y того же размера с получением результата x void Sub (Rational *x, Rational *y, int n) { while (--n >= 0) { *x = *x - *y++; ++x; } }
// Деление рационального массива x размером n на // рациональное число v с получением результата x void Div (Rational *x, Rational v, int n) { while (--n >= 0) { *x = *x / v; ++x; } }
// Получить модуль рационального массива // Если модуль равен 0, возвращается 0 // Если корень извлекается точно, возвращается 1, значение в y // Если корень не извлекается точно, возвращается 2, // извлеченное значение в y, подкоренное выражение в z int Mod (Rational *x, int n, Rational &y, Rational &z) { Rational s;
while (--n >= 0) { s = s + *x * *x; ++x; }
return s.Sqrt (y, z); }
// Присваивание одного рационального массива другому void Set (Rational *a, Rational *b, int n) { while (--n >= 0) { *a++ = *b++; } }
// Печать рационального массива void Print (Rational *a, int n) { int i;
cout << "{"; for (i = 0; i < n; ++i) { cout << a[i]; cout << (i == n - 1? "}\n": ", "); } }
// Печать рационального массива с учетом неизвлеченного квадратного корня void Print (int e, Rational *a, int cnt, Rational b) { int i, m, n, len;
// Получить значение подкоренной рациональной дроби m = b.GetM (); n = b.GetN ();
// Если эта дробь не целая, избавимся от иррациональности знаменателя if (n!= 1) { m *= n; Rational d(n); Div (a, d, cnt); }
// Определим число десятичных знаков в подкоренном выражении len = sprintf (txt, "%d", m);
// Печать верхней черты квадратного корня cout << " "; for (i = 0; i < len; ++i) { cout << "_"; } cout << "\n";
// Печать обозначения вектора и подкоренного выражения cout << "e" << e << " = \\/" << m << " * ";
// Печать вектора Print (a, cnt); }
int main() { int i, j; int size, cnt; Rational y, z; Rational **a; Rational **b; Rational *s; bool yes; char c;
// Краткая информация о задании cout << rus ( "\n" " Задания к работе\n\n" "1. Разработайте модуль работы с рациональными числами.\n" "2. Разработайте программу ортогонализации системы векторов\n" " процессом Грамма - Шмидта. Система векторов вводится\n" " пользователем с клавиатуры. На выходе программы получите\n" " систему ортогональных и ортонормированных векторов.\n" "3. С помощью разработанной программы произведите\n" " ортогонализацию системы векторов из задания своего варианта.\n\n" );
// Цикл выполнения обработки очередной системы векторов for (;;) { // Ввод размерности системы векторов cout << rus ("Размер вектора? "); cin >> size;
cout << rus ("Количество векторов? "); cin >> cnt;
// Выделение памяти под вектора и ввод значений a = new Rational *[cnt]; b = new Rational *[cnt]; s = new Rational[size];
for (i = 0; i < cnt; ++i) { a[i] = new Rational[size]; cout << "\n"; for (j = 0; j < size; ++j) { cout << "a" << (i + 1) << "[" << (j + 1) << "] "; cin >> a[i][j]; } b[i] = new Rational[size]; }
cout << rus ("\nИсходные вектора:\n\n");
for (i = 0; i < cnt; ++i) { cout << "a" << (i + 1) << " = "; Print (a[i], size); }
cout << rus ("\nОртогональные вектора:\n\n");
for (i = 0; i < cnt; ++i) { Set (b[i], a[i], size); for (j = 0; j <= i - 1; ++j) { Mul (s, b[j], Scalar (a[i], b[j], size) / Scalar (b[j], b[j], size), size); Sub (b[i], s, size); }
cout << "b" << (i + 1) << " = "; Print (b[i], size); }
// Пока нет ни одного ортонормированного вектора yes = false;
for (i = 0; i < cnt; ++i) { switch (Mod (b[i], size, y, z)) {
case 1: // Квадратный корень извлекается точно if (!yes) { cout << rus ("\nОртонормированные вектора:\n\n"); yes = true; } cout << "e" << (i + 1) << " = "; Div (b[i], y, size); Print (b[i], size); continue;
case 2: // Квадратный корень не извлекается точно if (!yes) { cout << rus ("\nОртонормированные вектора:\n\n"); yes = true; } Div (b[i], y, size); Print (i + 1, b[i], size, z);; } }
if (!yes) { cout << rus ("\nНет ни одного ортонормированного вектора\n"); }
// Освобождаем занятую память delete[] s; for (i = 0; i < cnt; ++i) { delete[] a[i]; delete[] b[i]; } delete[] a; delete[] b;
// Анализируем продолжение или завершение работы for (;;) { cout << rus ("\nНажмите клавишу 'y' для продолжения работы" "\nили клавишу 'n' для выхода..."); if ((c = getch ()) == 'n' || c == 'N') return 0; if (c == 'y' || c == 'Y') { cout << "\n\n"; break; } } } } Не нашли, что искали? Воспользуйтесь поиском:
|