【编程题分享】c++ 用类实现 大整数加法与乘法


前言

本周老师布置了一道编程题目,让我们实现大整数的加法和乘法。刚好我太久没接触编程,正好用这道题练练手,我也明白在本学期算法会是一个关键难点,而我在这个方面也差的太远,而且类的使用也不大熟练(倒不是难,理解清楚一些基本的算法其实是不难的,主要还是因为我懒)

一、c++中的类

这里用到的知识点主要是类成员的访问和运算符重载。这里我把在菜鸟教程上的知识做一个摘录。同时也把我觉得有点陌生的友元函数,多态做一个笔记。

为什么要用类来实现

运算符重载后实现起来看着很美观,有一种雅致和简约的美。

类的定义

定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
在这里插入图片描述

类的继承

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

class derived-class: access-specifier base-class

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。

我们可以根据访问权限总结出不同的访问类型,如下所示:

访问publicprotectedprivate
同一个类yesyesyes
派生类yesyesno
外部的类yesnono

(这个表格的制作花了不少时间,实际上可以很简单就画出来,害)

  • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
  • 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
  • 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

类的友元函数和友元类

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:

class Box
{
   double width;
public:
   double length;
   friend void printWidth( Box box );
   void setWidth( double wid );
};

因为友元函数没有this指针,则参数要有三种情况:

  • 要访问非static成员时,需要对象做参数;
  • 要访问static成员或全局变量时,则不需要对象做参数;
  • 如果做参数的对象是全局对象,则不需要对象做参数.

可以直接调用友元函数,不需要通过对象或指针

多态

to be continued 这个相对来说复杂一点,以后如果有空再补

运算符重载

您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

Box operator+(const Box&);

二、代码解释

数据解释

class number
{
	private:
		int *value;
		int length;
	public:
		void show_value() //展示数据的结果
		{
			for(int i = 0;i < this->length;i++) cout<<*(this->value+i);
			cout<<endl;
		}
		number operator+(number a) //加法核心
		{
			//为了展示放在后面
		}
		void set_value(int *b) //用来初始化值的,现在想想看用构造函数可能要方便些
		{
			this->value = b;
		}
		
		void set_length(int d)
		{
			this->length = d;	
		}
		
		number operator*(number c)
		{
			//为了美观放在后面
		}
};

核心算法解释

number operator+(number a) 
{
	number e;
	int v_length = max(this->length,a.length)+1;
	int *v = new int[v_length];
	for(int i = 0;i < v_length;i++)	v[i] = 0;
	int carry = 0;
	for(int i = 1;i <= min(this->length,a.length);i++)
	{
		int temp = this->value[this->length-i] + a.value[a.length-i] + carry;
		carry = temp/10;
		*(v + v_length - i) = temp%10;
	}//在两个大数都有位的基础上进行一个加法
	if(a.length < this->length) //判断哪个大数更长,则继续加进位
	{
		for(int i = a.length+1;i <= this->length;i++)
		{
			if(this->value[this->length-i]+carry < 10)
			{
				*(v+v_length-i) = this->value[this->length-i]+carry;
				carry = 0;
			}
			else
			{
				*(v+v_length-i) = (this->value[this->length-i]+carry)%10;
				carry = 1;
			}
		}
	}
	if(a.length > this->length)
	{
		for(int i = this->length+1;i <= a.length;i++)
		{
			if(a.value[a.length-i]+carry < 10)
			{
				*(v+v_length-i) = a.value[a.length-i]+carry;
				carry = 0;
			}
			else
			{
				*(v+v_length-i) = (a.value[a.length-i]+carry)%10;
				carry = 1;
			}
		}
	}
	if(carry == 1)
	{
		v[0] = 1;
		e.set_value(v);//通过指针是否加1来决定是否取第一位
		e.set_length(v_length);
		return e;
	}
	else 
	{
		e.set_value(v+1);
		e.set_length(v_length-1);
		return e;
	}
}
number operator*(number c)
{
	int flag = 0;
	number result;
	for(int i = this->length - 1;i >= 0;i--)
	{
		int carry = 0;
		number temp1;
		int *v = new int[c.length+this->length-i];//这里根据乘的哪一位使后面扩充0,例如,如果乘的百位,则扩充两个0,方便之后相加
		for(int k = 0;k < c.length+this->length-i;k++)	v[k] = 0;
		for(int j = c.length - 1;j >= 0;j--)//双重迭代,先单独乘以一位,再把所有乘以一位的积加起来
		{
			int temp2 = this->value[i] * c.value[j] + carry;
			carry = temp2 / 10;
			v[j+1] = temp2 % 10; 
		}
		if(carry != 0)
		{
			v[0] = carry;
			temp1.set_length(c.length+this->length-i);
			temp1.set_value(v);
		}
		else
		{
			temp1.set_length(c.length+this->length-i-1);
			temp1.set_value(v+1);
		}
		if(i == this->length - 1)
		{
			result.set_length(temp1.length);
			result.set_value(temp1.value);
		}
		else
		{
			result = result + temp1;
		}
	}
	return result;
}
};

测试结果

int main()
{
	string a,b;
	number num1,num2,num3,num4; 
	int *temp1,*temp2;
	int length1,length2;
	cout<<"请输入第一个大数;"; 
	cin>> a;
	cout<<endl; 
	cout<<"请输入第二个大数;"; 
	cin>> b;
	cout<<endl;
	length1 = a.size();
	length2 = b.size();
	num1.set_length(length1);
	num2.set_length(length2);
	temp1 = new int[length1];
	temp2 = new int[length2];
	for(int i = 0;i < length1;i++)
	{
		*(temp1+i) = a[i] - 48;
	}
	for(int i = 0;i < length2;i++)
	{
		*(temp2+i) = b[i] - 48;
	}
	num1.set_value(temp1);
	num2.set_value(temp2);
	num3 = num1 + num2;
	num4 = num1 * num2;
	cout<<"加法结果为:";
	num3.show_value();
	cout<<endl;
	cout<<"乘法结果为:";
	num4.show_value();
	cout<<endl;
}

>请输入第一个大数: 99999999999999999999999999999999999999999999999999999999999999999999999999

>请输入第二个大数: 99999999999999999999999999999999999999999999999999999999999999999999999999999

加法结果为:100099999999999999999999999999999999999999999999999999999999999999999999999998

乘法结果为:9999999999999999999999999999999999999999999999999999999999999999999999999899900000000000000000000000000000000000000000000000000000000000000000000000001

总结

因为太久没用c++了我甚至对于一个for循环的条件编错了还半天看不出来,最后导致浪费了大量时间,这种初学者的错误我既然也会犯,还是长点心吧。除此之外就是对于类和指针的使用要稍微熟悉了一点,顺便力扣的题目得慢慢开始刷起来了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值