面向对象程序设计实验——编写Rational类

实验任务与要求

编写一个表示有理数的类Rational。(有理数就是分数,包含分子与分母,均为整数)。要求:
	1)定义一个命名空间Numeric,在该空间中定义类Rational;
	2)编写默认构造函数,构造一个有理数0;
	3)编写带参数列表的构造函数Rational (int, int ),要求使用初始化列表;
	4)编写复制构造函数;
	5)编写赋值操作=;
	6)编写四个友元函数add、sub、mul、div,对两个Rational对象表示的有理数分别进行
	相加、相减、相乘、相除运算;
	(例:Rational x(1,2),y(1,3);分别表示有理数,则Rational z = add(x,y);之后,z表示)
	7)重载上述四个函数,实现有理数与整数的相加、相减、相乘、相除运算;
	(例:Rational x(1,2);表示有理数,则		Rational z = add(x,1),之后,z表示)
	8)编写成员函数getValue(),返回用浮点数表示的有理数,要求写成常函数。
	(例:Rational x(1,2);表示有理数,则x.getValue()返回0.5)
	9)编写友元函数lessThan,比较两个有理数的大小,返回bool类型。
	(例:Rational x(1,2),y(1,3);则bool b = lessThan(x,y);之后b为false)
	10)编写main函数,使用using namespace Numeric;来访问Numeric::Rational类。
	编写代码测试Rational类。
	11)在main函数中,随机生成10个有理数,形成一个有理数数组,
	并利用lessThan函数以及任意一种排序算法,对这10个有理数进行从小到大排序,输出排序结果。

代码解析

定义一个命名空间Numeric

下面展示代码片段 Numeric

// 命名空间内定义类及类的成员函数
// 本文简化设计,将函数体一同编写进类中
// 为代码清晰,可自定义头文件
namespace Numeric {
	/*表示有理数的类*/
	class Rational {
	public:
		// 默认构造函数,构造一个有理数0
		Rational() :numerator(0), denominator(1) {}
		// 带参数列表的构造函数,要求使用初始化列表
		Rational(int _a, int _b) :numerator(_a), denominator(_b) {}
		// 复制构造函数
		Rational(const Rational& rational) {}
		// 编写赋值操作 = 
		Rational& operator=(const Rational& rational) {}
		
	private:
		int numerator;  // 分子
		int denominator;  // 分母
	public:
		// 分数化简,参数为一个Rational对象
		Rational& fractionSimplify() {}
		
		// 有理数相加,参数为两个Rational对象
		friend Rational add(const Rational& x, const Rational& y) {}
		// 重载函数,实现有理数与整数的相加
		friend Rational add(const Rational& x, const int y) {}

		// 有理数相减,参数为两个Rational对象,
		friend Rational sub(const Rational& x, const Rational& y) {}
		// 重载函数,实现有理数与整数的相减
		friend Rational sub(const Rational& x, const int y) {}

		// 有理数相乘,参数为两个Rational对象,
		friend Rational mul(const Rational& x, const Rational& y) {}
		// 重载函数,实现有理数与整数的相乘
		friend Rational mul(const Rational& x, const int y) {}

		// 有理数相除,参数为两个Rational对象,
		friend Rational div(const Rational& x, const Rational& y) {}
		// 重载函数,实现有理数与整数的相除
		friend Rational div(const Rational& x, const int y) {}
		
		// 返回用浮点数表示的有理数,参数为两个Rational对象,要求写成常函数
		float getValue()const {}
		// 比较两个有理数的大小,参数为两个Rational对象,返回bool类型
		friend bool lessThan(const Rational x, const Rational y) {}
	};
}

Rational类的成员变量

下面展示代码片段 。

private:
	int numerator;  // 分子
	int denominator;  // 分母

编写默认构造函数

下面展示代码片段 Rational()
直接初始化,为避免除零异常,分母初始化为1

// 默认构造函数,构造一个有理数0
Rational() :numerator(0), denominator(1) {}
// 带参数列表的构造函数,要求使用初始化列表
Rational(int _a, int _b) :numerator(_a), denominator(_b) {}

编写复制构造函数

下面展示代码片段。

Rational(const Rational& rational) {
	numerator = rational.numerator;
	denominator = rational.denominator;
}

编写赋值操作=

下面展示代码片段。

Rational& operator=(const Rational& rational) {
	if (this != &rational) {
		numerator = rational.numerator;
		denominator = rational.denominator;
	}
	return *this;
}

分数化简

用于简化后续计算。

下面展示代码片段。

Rational& fractionSimplify() {
	int up, under;
	if (this->getValue() > 1) {  // 假分数
		up = this->denominator;
		under = this->numerator;
	}
	else {
		up = this->numerator;
		under = this->denominator;
	}
	while (under % up != 0) {
		int temp = under;
		under = up;
		up = temp % up;
	}
	this->numerator /= up;
	this->denominator /= up;
	return *this;
}

编写友元函数

以add为例。
下面展示代码片段 add

friend Rational add(const Rational& x, const Rational& y) {
	int _numerator = x.numerator * y.denominator + y.numerator * x.denominator;
	int _denominator = x.denominator * y.denominator;
	return Rational(_numerator, _denominator).fractionSimplify();
}

编写重载函数

以add为例。
下面展示代码片段 add

friend Rational add(const Rational& x, const int y) {
	int _numerator = x.numerator + y * x.denominator;
	int _denominator = x.denominator;
	return Rational(_numerator, _denominator).fractionSimplify();
}

main函数测试

下面展示代码。

int main(void) {
	using namespace Numeric;
	std::cout << name << " " << ID << std::endl;
	int numY = 2;
	Rational testX(1, 2);
	Rational testY(3, 4);
	Rational testOut;
	std::cout << "两个有理数算数运算:" << testX.getValue() << " , " << testY.getValue() << std::endl;
	testOut = add(testX, testY);
	std::cout << "Add reasult = " << testOut.getValue() << std::endl;

	testOut = sub(testX, testY);
	std::cout << "Sub reasult = " << testOut.getValue() << std::endl;

	testOut = div(testX, testY);
	std::cout << "Div reasult = " << testOut.getValue() << std::endl;

	testOut = mul(testX, testY);
	std::cout << "Mul reasult = " << testOut.getValue() << std::endl;

	std::cout << "有理数与常数算数运算:" << testX.getValue() << " , " << numY << std::endl;
	testOut = add(testX, numY);
	std::cout << "Add reasult = " << testOut.getValue() << std::endl;

	testOut = sub(testX, numY);
	std::cout << "Sub reasult = " << testOut.getValue() << std::endl;

	testOut = div(testX, numY);
	std::cout << "Div reasult = " << testOut.getValue() << std::endl;

	testOut = mul(testX, numY);
	std::cout << "Mul reasult = " << testOut.getValue() << std::endl;

	std::srand(int(time(0)));
	std::vector<Rational> rationals;
	for (int i = 0; i < 10; ++i) {  // 随机生成10个有理数,形成一个有理数数组
		int _numerator = (int)std::rand() % 10 + 1;
		int _denominato = (int)std::rand() % 10 + 1;
		Rational gener(_numerator, _denominato);
		rationals.push_back(gener);
	}
	for (unsigned int i = 0; i < rationals.size() - 1; ++i) {  // 冒泡排序,升序
		for (unsigned int j = 0; j < rationals.size() - 1 - i; ++j)
			if (!lessThan(rationals[j], rationals[j + 1])) {
				Rational temp = rationals[j];
				rationals[j] = rationals[j + 1];
				rationals[j + 1] = temp;
			}
	}
	std::cout << "排序结果:" << std::endl;
	for (unsigned int i = 0; i < rationals.size(); ++i) {  // 输出排序结果
		std::cout << rationals[i].getValue() << std::ends;
	}
	return 0;
}

测试截图

这是测试样例的测试结果

写在最后

本文作者刚开始学C++,如有问题或不对之处,欢迎指摘
代码仅供参考,问题实现范式不唯一,希望能给读者带来启发


版权声明:本文为weixin_44148685原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。