Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 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;

}

}

}

}






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных