Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.95/19: Рейтинг темы: голосов - 19, средняя оценка - 4.95
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
1

Простенький класс работы с комплексными числами.

29.09.2011, 22:17. Показов 3734. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер, уважаемые!
На днях решил вспомнить то, чему учили в университете и понял, что много чего забыл. Попробовал написать класс работы с комплексными числами. Вот что получилось. Скорее всего получилось очень и очень коряво. Вот именно за этим к Вам, уважаемые, и обращаюсь. Вопросы - внизу.

Драйвер класса.
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
#include "stdafx.h"
#include "complex.h"
#include <iostream>
#include <iomanip>
using namespace std;
 
int main(){
    complex * number, sum, diff; // Указатель на класс, объект "сумма", объект "разность".
    float real, im; // Вспомогательные переменные.
    unsigned short int size, num1, num2; // Размер массива объектов, номера "активных" чисел.
    
    cout << setw(20) <<"***Driver for complex class***" << endl;
    do{
        cout << "Input the qt. of elements: ";
        cin >> size;
    }
    while(size < 2);
    
    number = new complex[size];
    if(number == NULL){
        cout << "Sorry! Memory not captured!" << endl;
        system("pause");
        return 1;
    }
    
    for(int i = 0; i < size; i++){
        cout << "Input the real part of the number: ";
        cin >> real;
        cout << "Input the imaginary part of the number: ";
        cin >> im;;
        number[i].initNumber(real, im);
    }
 
    cout << "All numbers in array." << endl;
    for(int i = 0; i < size; i++){
        cout << i << ") ";
        number[i].printNumber();
    }
 
    do{
        cout << "Input two number for adding/minusing: ";
        cin >> num1 >> num2;
    }
    while(num1 < 0 || num1 > size || num2 < 0 || num2 > size);
    
    sum.initNumber((number[num1].getReal() + number[num2].getReal()), (number[num1].getImaginary() + number[num2].getImaginary()));
    cout << "Summ of " << num1 << " and " << num2 << ": ";
    sum.printNumber();
 
    cout << "Difference " << num1 << " and " << num2 << ": ";
    diff.initNumber((number[num1].getReal() - number[num2].getReal()), (number[num1].getImaginary() - number[num2].getImaginary()));
    diff.printNumber();
    
    system("pause");
    delete[]number;
    return 0;
}
Прототип класса.
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
#ifndef COMPLEX_H
#define COMPLEX_H
#ifndef IOSTREAM
#define IOSTREAM
#endif
#ifndef STDAFX_H
#define STDAFX_H
#endif
 
class complex{
    public:
        float addReal (float re1, float re2); // Сложение действительной части числа.
        float addIm (float im1, float im2); // Сложение мнимой части числа.
        float getReal(); // Изъятие действительной части числа.
        float getImaginary(); // Изъятие мнимой части числа.
        
        void printNumber (); // Вывод комплексного числа.
        void initNumber(float re, float im); // Инициализация действительной и мнимой частей числа.
    private:
        float Real; // Действительная часть числа.
        float Imaginary; // Мнимая часть числа.
};
 
#endif
Собственно, сами методы.

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
#include "stdafx.h"
#include "complex.h"
#include <iostream>
using namespace std;
 
float complex::getReal(){
    return Real;
}
 
float complex::getImaginary(){
    return Imaginary;
}
 
void complex::initNumber(float re, float im){
    Real = re;
    Imaginary = im;
}
 
void complex::printNumber(){
    cout << Real << " + " << Imaginary << "i" << endl;
}
 
float complex::addReal(float re1, float re2){
    return (re1 + re2);
}
 
float complex::addIm(float im1, float im2){
    return (im1 + im2);
}
А теперь, дамы и господа, вопросы newbie:
1) Можно ли заменить сумму и разность (для нее выписывать не буду) каким-либо отдельным методом, а не этим ужасом:
C++
1
sum.initNumber((number[num1].getReal() + number[num2].getReal()), (number[num1].getImaginary() + number[num2].getImaginary()));
Просто исходя из моих рассуждений, каждый метод класса относиться к конкретному объекту. Следовательно задействовать в методе одного объекта, данные другого возможно, но проблематично и этого делать не стоит.

2) Хотелось бы для каждого объекта сделать конструктор и деструктор не по умолчанию. Но не совсем понимаю, что туда можно засунуть кроме начальной инициализации. Подскажете?

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

Заранее спасибо за ответы!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.09.2011, 22:17
Ответы с готовыми решениями:

Класс для работы с комплексными числами
ne kompeliruet :S #ifndef COMPLEX0_H_ #define COMPLEX0_H_ class Complex { private: ...

класс для работы с комплексными числами
Здравствуйте.Надо: реализовать класс для работы с комплексными числами(аргумент, модуль, сложение,...

Описать класс для работы с комплексными числами
Описать класс для работы с комплексными числами (ввод-вывод, сложение, вычисление модуля)....

Класс Complex для работы с комплексными числами
Создать класс Complex для работы с комплексными числами. В классе переопределить арифметические...

15
71 / 76 / 9
Регистрация: 30.06.2011
Сообщений: 176
30.09.2011, 03:44 2
Через перегрузку операторов:
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
 class Complex
{
    float re, im;
public:
    Complex( float re =0.0f, float im =0.0f) : re(re), im(im) {}
    const Complex& operator = ( const Complex& complex)
    {
        re = complex.re;
        im = complex.im;
        return *this;
    }
    Complex operator + ( const Complex& complex) const
    {
        return Complex( re + complex.re, im + complex.im);
    }
    Complex operator - ( const Complex& complex) const
    {
        return Complex( re - complex.re, im - complex.im);
    }
    Complex operator * ( const Complex& complex) const
    {
        return Complex( re * complex.re - im * complex.im, re * complex.im + im * complex.re);
    }
};
1
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
30.09.2011, 05:39 3
Цитата Сообщение от Slimmy Посмотреть сообщение
Драйвер класса.
что такое "Драйвер класса"?

Цитата Сообщение от Slimmy Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
#ifndef COMPLEX_H
#define COMPLEX_H
#ifndef IOSTREAM
#define IOSTREAM
#endif
#ifndef STDAFX_H
#define STDAFX_H
#endif
//...
Зачет у тебя тут guard'ы для iostream и stdafx.h?
Где у тебя конструкторы? Где оператор присваивания? Зачем такие странные методы, как "сложишь действительные части", "сложить мнимые части", которые на самом деле выполняют одно и то же (т.е. складывают два вещественных числа)?
Где методы (или операторы), которые реализуют арифметику с самими комплексными числами?
0
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 05:49  [ТС] 4
Цитата Сообщение от Nameless One Посмотреть сообщение
что такое "Драйвер класса"?
Ну в моем понимании - это некий код, осуществляющий работу и тестирование этого самого класса.

Цитата Сообщение от Nameless One Посмотреть сообщение
Где у тебя конструкторы?
Вот как раз про них и спрашиваю. Конструктор используется по-умолчанию. Знаю, что так использовать очень и очень не хорошо.

Цитата Сообщение от Nameless One Посмотреть сообщение
Где методы (или операторы), которые реализуют арифметику с самими комплексными числами?
Проблема в том, что это до меня и не доходит. Имеем класс комплексных чисел. Он описывает один объект. То есть фактически, для того, чтобы сложить два комплексных числа нужно в одном объекте делать метод на взятие другого объекта из массива.
Может подскажете более действенную структуру класса (в плане методов, разумеется)?
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
30.09.2011, 05:56 5
Цитата Сообщение от Slimmy Посмотреть сообщение
о есть фактически, для того, чтобы сложить два комплексных числа нужно в одном объекте делать метод на взятие другого объекта из массива.
нет, класс комплексных чисел ничего не должен знать ни о каких массивах.
Цитата Сообщение от Slimmy Посмотреть сообщение
Может подскажете более действенную структуру класса (в плане методов, разумеется)?
Смотри пост #2. Там уже все подсказали
1
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 06:00  [ТС] 6
Цитата Сообщение от Nameless One Посмотреть сообщение
нет, класс комплексных чисел ничего не должен знать ни о каких массивах.
Вот и я тоже так думаю.

Цитата Сообщение от Nameless One Посмотреть сообщение
Смотри пост #2. Там уже все подсказали
Это если только на будущее. Не читал еще про перегрузку операторов. Все-равно спасибо.

А можно еще вопрос? Почему Вы спросили на счет проверки включения <iostream> и "stdafx"? Её разве осуществлять не нужно? Перестраховаться там и все дела.
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
30.09.2011, 08:03 7
Цитата Сообщение от Slimmy Посмотреть сообщение
Почему Вы спросили на счет проверки включения <iostream> и "stdafx"
то, что ты сделал:
  1. не нужно
    C тем, что guard'ы нужны для предотвращения повторного включения заголовочных файлов, никто не спорит. Обычно это делают так:
    C
    1
    2
    3
    4
    5
    6
    
    #ifndef ИМЯ_ХЕДЕРА_H
    #define ИМЯ_ХЕДЕРА_H
     
    // ... код хедера
     
    #endif
    И теперь сколько бы мы раз не указывали компилятору (с помощью директивы #include) подключить наш заголовочный файл, он будет подключен лишь один раз.
    Но зачем делать то же самое в своем хедере, к примеру, для iostream? Создатели твоего компилятора уже позаботились о том, чтобы iostream содержал подобные include guard'ы.
  2. скорее всего не будет работать так, как ты задумывал
    Забудем на минутку про предыдущий пункт и представим, что проверка включений стандартных заголовочных файлов в твоих заголовочных файлах является оправданным.
    Но с чего ты решил, что в iostream твоего компилятора (да и вообще, любого произвольного компилятора) защита от повторных включений осуществлена посредством определения именно символа IOSTREAM? К примеру, у меня (gcc) она осуществляется с помощью определения символа _GLIBCXX_IOSTREAM:
    C++
    1
    2
    3
    4
    5
    6
    
    #ifndef _GLIBCXX_IOSTREAM
    #define _GLIBCXX_IOSTREAM 1
     
    //...
     
    #endif
    И даже если перед включением твоего файла будет подключен iostream, то твой файл все равно никак не сможет об этом узнать.
  3. потенциально вредно
    Представим, что ты все же угадал с именем определяемого символа. Тогда рассмотрим следующую ситуацию. Имеем заголовочный файл bad_header_guard.hh:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    #ifndef BAD_HEADER_GUARD_HH
    #define BAD_HEADER_GUARD_HH
     
    // А вот так делать очень, очень плохо!
    #ifndef _GLIBCXX_IOSTREAM
    #define _GLIBCXX_IOSTREAM
    #endif
     
    #endif
    И файл main.cc:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    
    #include "bad_header_guard.hh"
    #include <iostream>
     
    int main()
    {
        std::cout << "It seem's like there's no iostream around" << std::endl;
        return 0;
    }
    Что же произойдет, если ты попытаешься собрать эту программу? Обрабатывая main.cc, препоцессор наткнется на директиву #include "bad_header_guard.hh" на первой строке. Он обработает этот файл bad_header_guard.hh, определит символы BAD_HEADER_GUARD_HH и _GLIBCXX_IOSTREAM, и вставит его содержимое в main.cc.
    Дальше, на второй строке main.cc, ему придется обрабатывать iostream. Но, т.к. символ _GLIBCXX_IOSTREAM уже определена раньше, то содержимое iostream не будет вставлено в main.cc, т.е. препроцессор полностью его проигнорирует! И в итого мы получаем ошибку компиляции:
    Код
    -*- mode: compilation; default-directory: "/home/nameless/samples/cpp/" -*-
    Compilation started at Fri Sep 30 14:56:51
    
    make -j8
    g++ -c -Wall -g -std=c++0x main.cc
    main.cc: В функции «int main()»:
    main.cc:6:5: ошибка: «cout» не является элементом «std»
    main.cc:6:65: ошибка: «endl» не является элементом «std»
    make: *** [main.o] Ошибка 1
    
    Compilation exited abnormally with code 2 at Fri Sep 30 14:56:51
1
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 16:23  [ТС] 8
Цитата Сообщение от Nameless One Посмотреть сообщение
то, что ты сделал:
не нужно
скорее всего не будет работать так, как ты задумывал
потенциально вредно
Фактически, я еще не разбирался с директивами препроцессора и как они устроены. Просто следую "шаблону", как дрессированная собака. Через пару глав дойду, надеюсь, что буду все это понимать.
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
30.09.2011, 16:48 9
Тут можно почитать про директивы препроцессора: Препроцессорные директивы в C/C++ (#include, #define и прочее)
1
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 16:54  [ТС] 10
Цитата Сообщение от Nameless One Посмотреть сообщение
Тут можно почитать про директивы препроцессора: Препроцессорные директивы в C/C++ (#include, #define и прочее)
Благодарю. Можете что-нибудь сказать о книге Харви и Пола Дейтлов? Я на данный момент её сейчас "третирую".
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
30.09.2011, 16:56 11
Не читал
0
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
01.10.2011, 21:23  [ТС] 12
Если кого интересует (хотя скорее всего нет, ибо тут все образованные люди, в отличии от меня), нашел выход из ситуации с суммой. Вспомнил, про передачу объекта в метод с помощью указателя.
C++
1
2
3
4
void complex::sumNumber(complex * num1, complex * num2){
    Real = num1->getReal() + num2->getReal();
    Imaginary = num1->getImaginary() + num2->getImaginary();
}
По аналогии с разностью. Хотя, можно наверное дополнительный bool параметр передавать, который будет отвечать за выбор операции, но это уже "чисто вкусовые прибамбасы".
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
02.10.2011, 06:09 13
Slimmy, если передавать объекты по значению, а не по указателю, то все равно ничего не изменится.
0
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
02.10.2011, 13:09  [ТС] 14
Цитата Сообщение от Nameless One Посмотреть сообщение
Slimmy, если передавать объекты по значению, а не по указателю, то все равно ничего не изменится.
При передаче по ссылке объект не копируется ведь, следовательно уменьшается время работы программы или я что-то путаю? Конечно, в таких "мини-прогах" на это абсолютно параллельно, но в больших проектах, где роль играет каждая сотая секунды - это принципиально, нет? Может я что-то не так понимаю.
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
03.10.2011, 17:47 15
Цитата Сообщение от Slimmy Посмотреть сообщение
При передаче по ссылке объект не копируется ведь, следовательно уменьшается время работы программы или я что-то путаю?
все правильно, но тогда корректнее будет передавать либо по константой ссылке, либо по указателю на константу, т.к. передаваемые объекты не модифицируются внутри метода

Добавлено через 23 часа 26 минут
Цитата Сообщение от Nameless One Посмотреть сообщение
все правильно
ну, это если не считать того, что метод sumNumber никак не вписывается в логику класса complex. По сути, следуя из интуитивного понимания комплексных чисел, наш класс, представляющий комплексное число, должен поддерживать как минимум следующие методы (конструкторы, деструкторы и аксессоры опускаю)
  • сложения/вычитания/умножения/деления на комплексное число. Каждая операция соответствует методу, принимающему один экземпляр класса complex и возвращающему новый новое комплексное число. Пример для операции сложения:
    C++
    1
    2
    3
    4
    
    complex complex::operator + (const complex& rhs) const
    {
       return complex(re + rhs.re, im + rhs.im);
    }
  • то же самое, только для действительных чисел
  • сравнение двух комплексных чисел (равны, не равны)
  • нахождение модуля и аргумента числа
  • нахождение сопряженного комплексного числа
Вроде все...
1
65 / 18 / 3
Регистрация: 09.10.2010
Сообщений: 97
03.10.2011, 19:56  [ТС] 16
То, что правильнее всего делать с перегрузкой операторов - это я уже понял, но пока багаж знаний не позволяет сделать это осознанно, а не по типу "да что тут думать? трясти нужно". На счет остальных добавленных методов - благодарю, сделаю. Просто делаю упражнения по книге, особо не задумываясь над содержанием.
0
03.10.2011, 19:56
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.10.2011, 19:56
Помогаю со студенческими работами здесь

Реализовать класс Complex для работы с комплексными числами
Комплексное число представляются парой действительных чисел (a, b), где a — действительная часть, ...

Создать класс для работы с тригонометрическими комплексными числами
Дана первоначальная задача (я ее решил):3. Создать класс для работы с тригонометрическими...

Создать класс для работы с тригонометрическими комплексными числами - C++
Создать класс для работы с тригонометрическими комплексными числами. Комплексное число в...

Реализовать класс Complex для работы с комплексными числами.
Реализовать класс Complex для работы с комплексными числами. Класс должен обеспечивать инкапсуляцию...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru