Написание класса Дроби на C++
Это довольно классическая задача, которая рано или поздно встречается каждому программисту. Я думаю, вы знаете, что компьютер не хранит вещественные числа точно и что погрешности, как правило вызванные округлением, имеют свойство накапливаться, а потому даже небольшая погрешность потенциально может сильно исказить результат арифметических операций.
Именно из-за этого класс Дроби часто необходим при работе с большими вычислениями, поскольку помогает хранить дробные числа точно (в виде двух целых чисел) и производить промежуточные расчёты без накопления погрешности.
Новый тип данных Fraction будет иметь два поля — числитель (numerator) и знаменатель (denominator). Знак будет храниться в числителе.
class Fraction < public: int numer, denom; Fraction(int n = 0, int d = 1) < //конструктор, на вход подаются два числа n и d numer = n; denom = d; >>
Если на входе одно число, оно записывается в числитель, а знаменатель по умолчанию равен 1. В этом случае мы получаем обычное целое число. Если объект создаётся без входных параметров, по умолчанию создаётся число 0.
Арифметические операции для дробей будем реализовывать с помощью перегрузки соответствующих операторов:
Fraction operator + (Fraction& other)
Вычитание выполняется как сложение с отрицательным числом:)
Fraction operator — (Fraction& other)
Умножение и деление (умножение на «перевёрнутую дробь»)
Fraction operator * (Fraction& other) < return Fraction( numer * other.numer, denom * other.denom ).reduce(); >Fraction operator / (Fraction& other)
Почти готово. Осталось прописать ввод/вывод дроби, и, самое интересное — сокращение дроби до несократимой. Для этого напишем функции input, show и reduce.
Начнём с сокращения: дробь станет несократимой, если числитель и знаменатель поделить на их НОД, поэтому его сначала нужно найти. Есть разные способы это сделать, я применю рекурсию (алгоритм Евклида):
int fract_nod(int a, int b)
Здесь важно, чтобы a было больше или равно b, а также чтобы числа были положительны, но это мы учтём в самой функции reduce.
Fraction reduce() < int a = max(abs(numer), abs(denom)), b = min(abs(numer), abs(denom)); int sgn; //знак нашей дроби if (numer * denom >= 0) sgn = 1; else sgn = -1; int nod = fract_nod(a, b); return Fraction(sgn * (abs(numer) / nod), abs(denom) / nod); >
Теперь нужно встроить эту функцию в операции сложения и умножения так, чтобы конечный результат был несократимой дробью:
Fraction operator + (Fraction& other) < return Fraction( numer * other.denom + denom * other.numer, denom * other.denom ).reduce(); //новое >
Fraction operator * (Fraction& other) < return Fraction( numer * other.numer, denom * other.denom ).reduce(); //новое >
Напишем функцию вывода:
void show() < cout << "\t" << numer; if (denom != 1) cout << "/"
Логично вводить дроби в том же формате, что и выводить, т.е. в виде m/n, где m — целое число, а n — натуральное. Поскольку мы пишем класс на плюсах, придётся повозиться со считыванием строки и преобразованием её в два числа (возможно, с отрицательным знаком).
Fraction input(string& s) < int n = 0, d = 0, deg = 0; int slash_pos = s.find('/'); //ищем разделитель if (slash_pos != s.npos) < //если он есть (число введено как дробь) int i = slash_pos - 1; //записываем в n число перед "/" while (i >-1) < if (s[i] != '-') n += (s[i] - 48) * pow(10, deg++); //сдвиг на 48, т.к. код "0" в ASCII = 48 else n = -n; i -= 1; >deg = 0; i = s.size() - 1; //записываем в d число после "/" while (i > slash_pos) < if (s[i] != '-') d += (s[i] - 48) * pow(10, deg++); else d = -d; i -= 1; >> else < //если число введено как целое d = 1; int i = s.size() - 1; while (i >-1) < if (s[i] != '-') n += (s[i] - 48) * pow(10, deg++); else n = -n; i -= 1; >> //создаём дробь с введёнными числами и сокращаем Fraction f; if (d) f = Fraction(n, d).reduce(); else f = Fraction(n); return f; >
Код целиком
#include #include using namespace std; int fract_nod(int a, int b) < if (b == 0) return a; return fract_nod(b, a % b); >class Fraction < public: int numer, denom; Fraction(int n = 0, int d = 1) < numer = n; denom = d; >Fraction reduce() < int a = max(abs(numer), abs(denom)), b = min(abs(numer), abs(denom)); int sgn; if (numer * denom >= 0) sgn = 1; else sgn = -1; int nod = fract_nod(a, b); return Fraction(sgn * (abs(numer) / nod), abs(denom) / nod); > void show() < cout Fraction operator + (Fraction& other) < return Fraction( numer * other.denom + denom * other.numer, denom * other.denom ).reduce(); >Fraction operator - (Fraction& other) < return Fraction(numer, denom) + Fraction(-other.numer, other.denom); >Fraction operator * (Fraction& other) < return Fraction( numer * other.numer, denom * other.denom ).reduce(); >Fraction operator / (Fraction& other) < return Fraction(numer, denom) * Fraction(other.denom, other.numer); >>; Fraction input(string& s) < int n = 0, d = 0, deg = 0; int slash_pos = s.find('/'); if (slash_pos != s.npos) < int i = slash_pos - 1; while (i >-1) < if (s[i] != '-') n += (s[i] - 48) * pow(10, deg++); else n = -n; i--; >deg = 0; i = s.size() - 1; while (i > slash_pos) < if (s[i] != '-') d += (s[i] - 48) * pow(10, deg++); else d = -d; i--; >> else < d = 1; int i = s.size() - 1; while (i >-1) < if (s[i] != '-') n += (s[i] - 48) * pow(10, deg++); else n = -n; i--; >> Fraction f; if (d) f = Fraction(n, d).reduce(); else f = Fraction(n); return f; >
Как записать натуральную дробь?

Привести натуральную дробь к несократимому виду
1) Описать процедуру Socr(a,b,p,q) от целых параметров (b \neq 0), которая приводит дробь a/b к.
Записать как обычную математическую дробь
а) Записать как обычную математическую дробь 0,0123456789Е+0,7 б) Сколько байтов занимает.
Как написать класс «несократимая дробь» (т.е. дроби 2/4, 4/8 и т.п. есть дробь 1/2)?
Я только начанаю знакомство с C++. В классе реализовать следующие методы: конструкторы (по.

Как сделать натуральную сортировку одномерного массива?
В языке PHP есть функция natsort() которая сортирует массив используя алгоритм "natural order".
6279 / 3564 / 898
Регистрация: 28.10.2010
Сообщений: 5,926
Inkvizzz, в смысле? В C нет дробей, есть числа с плавающей точкой, 5/9 так и запишите, если хотите, чтобы деление происходило на цело, иначе 5.0 / 9.0.
![]()
4918 / 3914 / 1619
Регистрация: 24.04.2014
Сообщений: 11,433
числитель или знаменатель должен иметь вещественный тип.
Например 5.0/9 или ((double)5)/9
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Как найти натуральную величину треугольника способом замены плоскостей проекций
Как найти натуральную величину треугольника способом замены плоскостей проекций
Рекурсия: возвести число А в натуральную степень n за как можно меньшее количество умножений
Задание такое: Возвести число А в натуральную степень n за как можно меньшее количество умножений.

Умножить дробь на дробь и получить ответ в виде несократимой дроби
Даны две дроби A/B и C/D (где А, В, С, D — натуральные числа). Умножить дробь на дробь и получить.
Рациональную дробь перевести в цепную дробь
procedure Express; var a,b,t: integer; q: char; begin repeat writeln (‘введите числитель=’);.
Процедура возведения в натуральную степень
Помогите решить 2 задачи и обьяснить их,а то я их понять не могу=( 1.Алгоритм сложности O(N). Дан.
Возвести натуральное число в натуральную степень
Напишите программу, которая вводит натуральные числа A и N и вычисляет A N . По теме циклы ! .
Или воспользуйтесь поиском по форуму:
Как записать дробь в c
Всем доброе время суток. Помогите, пожалуйста, исправить код программы, которая задает класс «Дроби» и включает в себя операции сложения, вычитания, деления, умножения и поиск наименьшего общего знаменателя при сложении и вычитании. исходник работает, но препод говорит, что не тот принцип построения.
#include #include using namespace std; class Drobi < private: int x1,y1,x2,y2; public: Drobi(int a, int b, int e, int f) < x1=a; y1=b; x2=e; y2=f; >float summa (float c, float d, float k) < return (c+d)/k; >float raznost (float c, float d, float k) < return (c-d)/k; >float proizv (float x1, float y1, float x2, float y2) < return ((x1/y1)*(x2/y2)); >float chastnoe (float x1, float y1, float x2, float y2) < return ((x1/y1)/(x2/y2)); >>; void main () < setlocale (0,""); int a,b,e,f; cout>a; cout>b; cout>e; cout>f; Drobi A(a,b,e,f); cout > cout
Участник клуба
Регистрация: 15.07.2008
Сообщений: 1,933
Вероятнее всего имелось ввиду, что класс должен представляет одну единственную дробь, в то время как у вас он представляет сразу две дроби. Операции сложения, вычитания, умножения и деления скорее всего надо было делать перегрузкой соответствующих операторов(если вы такое уже проходили, естественно). То есть примерно так:
class Drobi < int chislitel; unsigned int znamenatel; public: Drobi(); Drobi(int); Drobi(int, unsigned int); // Drobi(double); // Это в общем не обязательно, но если реализуете, то, вероятно, положительно скажется на оценке :) Drobi operator+ (Drobi); Drobi operator+ (int); // Drobi operator+ (double); Drobi operator- (Drobi); Drobi operator- (int); //. то же самое для *, /
Реализацию сами опишите. Должна быть возможность использовать так:
int main() < Drobi n(2, 3); Drobi m(3, 2); Drobi l = m + n; l = l / 2; Drobi d(10); d = d * l; return 0; >
Желательно также реализовать операторы *=, /=, +=, -=, а также перегрузить хотя бы оператор вывода для ostream(
Последний раз редактировалось netrino; 29.11.2009 в 18:31 .
Регистрация: 29.11.2009
Сообщений: 3
Мы писали такую прогу. Вот она:
class Rational ;
Rational::Rational (int chislit, int znamenat) > Rational Rational::Add (const Rational&s) const < int c; Rational Sum; Sum.a=a*s.b+b*s.a; Sum.b=b*s.b; if (Sum.a>Sum.b) c=Nod (Sum.b, Sum.a); else c=Nod (Sum.b, Sum.a); Sum.a=Sum.a/c; Sum.b=Sum.b/c; return Sum; > Rational Rational::Sub (const Rational&s) const < int c; Rational Sum; Sum.a=a*s.b-b*s.a; Sum.b=b*s.b; if (Sum.a>Sum.b) c=Nod (Sum.b, Sum.a); else c=Nod (Sum.b, Sum.a); Sum.a=Sum.a/c; Sum.b=Sum.b/c; return Sum; > Rational Rational::Mult (const Rational&s) const < int c; Rational Sum; Sum.a=a*s.a; Sum.b=b*s.b; if (Sum.a>Sum.b) c=Nod (Sum.b, Sum.a); else c=Nod (Sum.b, Sum.a); Sum.a=Sum.a/c; Sum.b=Sum.b/c; return Sum; > Rational Rational::Div (const Rational&s) const < int c; Rational Sum; Sum.a=a*s.b; Sum.b=b*s.a; if (s.a==0) ; if (Sum.a>Sum.b) c=Nod (Sum.b, Sum.a); else c=Nod (Sum.b, Sum.a); Sum.a=Sum.a/c; Sum.b=Sum.b/c; return Sum; > void Rational::Print () const void Rational::Change (int d, int e) ; if (a>b) f=Nod(a,b); else f=Nod(b,a); a=a/f; b=b/f; > int Rational::Nod (int c, int d) const
int main ()
| mishutka999 |
| Посмотреть профиль |
| Найти ещё сообщения от mishutka999 |
Написание дроби c++ [закрыт]
Закрыт. Этот вопрос необходимо уточнить или дополнить подробностями. Ответы на него в данный момент не принимаются.
Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение.
Закрыт 7 лет назад .
Как в c++ написать дробь, чтобы знаменатель был под числителем?
Отслеживать
6,488 6 6 золотых знаков 24 24 серебряных знака 31 31 бронзовый знак
задан 28 фев 2016 в 18:12
Егор Смирнов Егор Смирнов
55 1 1 серебряный знак 8 8 бронзовых знаков
Что вы имеете в виду? Просто вывести в текстовом режиме? в три строки. Так первые Mathematica работали - страшно смотреть было 🙂 Если неверно вас понял - уточните вопрос, pls.
28 фев 2016 в 18:13
Да, в текстовом режиме
28 фев 2016 в 18:18
Вам нужно одиночные дроби выводить или в составе выражения?
28 фев 2016 в 19:03
@velikodniy в составе выражения
28 фев 2016 в 19:46
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
За отсутствием форматирования в комментариях вынужден прибегнуть к ответу 🙂
В тексте - если a/b никак не устраивает - только в первой строке выводить знаменатель, во второй - рисовать знак дроби, и в третьей - числитель.
5 8 31 - + - = -- 2 3 6
Отслеживать
ответ дан 28 фев 2016 в 18:21
219k 15 15 золотых знаков 120 120 серебряных знаков 230 230 бронзовых знаков
И это компилируется? )
28 фев 2016 в 19:03
@gil9red казалось бы при чем тут вывод и компиляция?
28 фев 2016 в 19:24
@gil9red cout << "5 8 31\n- + - = --\n2 3 6\n" - вполне, почему бы и нет.
28 фев 2016 в 22:29
- c++
- математика
-
Важное на Мете
Похожие
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.26.3951