Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- // Класс обыкновенная дробь
- class Fraction {
- private:
- unsigned m_num; // Числитель
- unsigned m_denum; // Знаменатель
- bool m_sign; // Знак (true - минус, false - плюс)
- // Приватный метод для нахождения наибольшего общего делителя (алгоритм евклида)
- // Возвращает наибольший общий делитель
- unsigned getGCD(unsigned a, unsigned b) {
- while (a != b) {
- if (a > b)
- a = a - b;
- else
- b = b - a;
- }
- return a;
- }
- public:
- // Конструктор по-умолчанию
- Fraction(): m_num(0), m_denum(1), m_sign(false) {}
- // Конструктор, принимает числитель, знаменатель и знак (true значит минус)
- Fraction(unsigned numerator, unsigned denumerator, bool sign = false):
- m_num(numerator), m_denum(denumerator), m_sign(sign)
- {
- if (m_denum == 0) {
- std::cout << "Ошибка! Знаменатель не может быть равен нулю и будет задан значением 1." << std::endl;
- m_denum = 1;
- }
- unsigned gcd;
- // Сокращяем числитель и знаменатель
- // Пока наибольший общий делитель числителя и знаменателя не равен 1 -
- // делим их на него и записываем в них же результат этого деления
- while ((gcd = getGCD(m_num, m_denum)) != 1) {
- m_num /= gcd;
- m_denum /= gcd;
- }
- }
- // Конструктор из десятичной дроби
- Fraction(double frac) {
- setFromDecimal(frac);
- }
- // Метод превращает дробь в обратную (меняет числитель и знаменатель местами)
- void reverse() {
- unsigned tmp = m_num; // записываем значение числителя во временную переменную tmp
- m_num = m_denum; // присваеваем числителю значения знаменателя
- m_denum = tmp; // присваеваем знаменателю значения числителя, сохраненное в переменной tmp
- }
- // Метод преобразует обыкновенную дробь в десятичную и возвращает полученное значение в виде числа типа double
- double toDecimal() {
- // Дробь можно преобразовать в конечную десятичную, если знаменатель раскладывается ТОЛЬКО на множители 2 и 5
- bool check = true; // Флаг, показывающий, можно ли преобразовать в десятичную дробь
- unsigned denum = m_denum; // Записываем знаменатель в новую переменную для расчетов
- // Цикл пока denum больше одного
- while(denum > 1) {
- // Если denum делится на 2 без остатка - делим его на 2 и в него же записываем результат
- if ((denum % 2) == 0) {
- denum /= 2;
- }
- // Если denum делится на 5 без остатка - делим его на 5 и в него же записываем результат
- else if ((denum % 5) == 0) {
- denum /= 5;
- }
- // Если нет - устанавливаем флаг в false и прерываем цикл
- else {
- check = false;
- break;
- }
- }
- // Если число нельзя преобразовать в конечную десятичную дробь - выводим предупреждение
- if (!check) {
- std::cout << "Дробь " << m_num << "/" << m_denum << " нельзя преобразовать в конечную десятичную!"
- << "Будет возвращен приблизительный результат." << std::endl;
- }
- // Преобразуем m_num в double (т.к. результат деления unsigned/unsigned всегда целочисленный) и делим на знаменатель m_denum
- if (m_sign)
- return -double(m_num) / m_denum;
- else
- return double(m_num) / m_denum;
- }
- // Метод устанавливает обыкновенную дробь из десятичной
- void setFromDecimal(double number) {
- m_sign = false;
- // Устанавливаем знак, если число отрицательно
- if (number < 0.0) {
- m_sign = true;
- number = -number;
- }
- // Знаменатель равен 1
- unsigned denum = 1;
- // Числитель равен десятичной дроби
- double numerator = number;
- // Умножаем числитель и знаменатель на 10, пока у числителя есть числа после запятой
- while (numerator - unsigned(numerator) != 0) {
- numerator *= 10;
- denum *= 10;
- }
- // Устанавливаем числитель и знаменатель класса
- m_num = unsigned(numerator);
- m_denum = denum;
- unsigned gcd;
- // Пока наибольший общий делитель числителя и знаменателя не равен 1 -
- // делим их на него и записываем в них же результат этого деления
- while ((gcd = getGCD(m_num, m_denum)) != 1) {
- m_num /= gcd;
- m_denum /= gcd;
- }
- }
- void print() {
- if (m_sign)
- std::cout << "-";
- std::cout << m_num << "/" << m_denum << std::endl;
- }
- };
- int main() {
- setlocale(LC_CTYPE, "rus");
- // Создаем обыкновенные дроби
- Fraction a(3, 2); // Дробь 3/2
- Fraction b(15, 30, true); // Дробь 1/2
- Fraction c(11, 40); // Дробь 11/40
- // Из десятичной дроби
- Fraction d(0.1725); // Дробь 69/400
- // Выводим на экран
- std::cout << "Обыкновенные дроби: " << std::endl;
- a.print();
- b.print();
- c.print();
- d.print();
- // Выводим на экран в десятичном виде
- std::cout << "В десятичном виде: " << std::endl;
- std::cout << a.toDecimal() << std::endl;
- std::cout << b.toDecimal() << std::endl;
- std::cout << c.toDecimal() << std::endl;
- std::cout << d.toDecimal() << std::endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement