C++ 高精度算法

提示:


前言

提示:这里可以添加本文要记录的大概内容:

例如:洛谷阶乘题目,unsigned long long不够大,需要用字符串进行高精度运算


提示:以下是本篇文章正文内容,下面案例可供参考

一、数据的接收方法和存储方法

可采用字符串方式输入,这样可输入位数很长的数,利用字符串函数和操作运算,将每一位取出,存入数组中。
存储数字时采用倒序存储,原因为:
正序存储个位在最后,如果增加数字的量级如从万到十万,那么每个数量单位的数字都需要改变;相反,个位存储在a[0],扩大10的n次倍只要改变一位数组元素的值即可。

//数字位数=strlen( ),对应数组下标为strlen-1-i
for (int i = 0 ; i < len_a ; i++) 
  s1[i] = a[strlen(a)-1-i]-'0';
   
for (int i = 0 ; i < len_b ; i++) 
  s2[i] = b[strlen(b)-1-i]-'0';
    
int len_max = max(lena,lenb);

二、四种情况

1.加法

代码如下(示例):

for (int i = 0 ; i < len_max ; i++)
    {
    //首先加上c[i]的原因是将可能进的位加上
        c[i] = c[i]+s1[i]+s2[i];****
    //将进位的情况包含在内
        c[i+1] = c[i]/10;
        c[i] = c[i]%10;
    }

还需要考虑600+500,原本len_max=3,相加后变成4位,由于开始c[i]全部赋值为0
因此如果出现增加位数的可能,c[len_max]为1,因此添加一行代码

if (c[len_max]) 
	cout<<"1";

2.减法

首先考虑减数和被减数位置,进行如下讨论
(1)a,b直接定义为string类变量

if(len_a < len_b ||(lena==lenb && a < b)) //string类可以直接比较两个字符串的字典序
    {
    swap(a,b);
    swap(lena,lenb);
    cout<<"-";
    } 

(2)a,b为字符数组
(类似于strcmp的自定义)

int cha=0;
 int len_a, len_b
 len_a = strlen(a);
 len_b = strlen(b);
 int max = 0;
 if (len_a > len_b)
     max = len_a;
 else
     max = len_b;
 int cha=0;
 for (int i = 0; i < max; i++)
 {
     cha = a[max-1] - b[max-1];
     if (cha != 0)
         break;
 }
if(cha<0)
{
char a_[len_a+1],b_[len_b+1];
//记得赋值为'\0',此处省略
for(int i=0;i<len_b+1;i++)
{
	   a_[i]=b[i];
	   b_[i]=a[i];
}
	   swap(lena,lenb);
	   //到此,已经交换完成a和b两个数组
}
else
{
	for(int i=0;i<len_a+1;i++)
	{
		   a_[i]=a[i];
		   b_[i]=b[i];
	}
}

然后进行减法运算

//先进行存储
for (int i = 0 ; i < len_a ; i++) 
  s1[i] = a_[strlen(a)-1-i]-'0';
   
for (int i = 0 ; i < len_b ; i++) 
  s2[i] = b_[strlen(b)-1-i]-'0';
  
//模拟竖式减法
for (int i = 0; i < len_a; i++) //这个时候数组长度a_>=b_
{
    if (s1[i]<s2[i]) 
    {
        //有借位
        s1[i+1]--;
        s1[i] += 10;
    }
    c[i] = s1[i] - s2[i];
}

//删去前导的0
while(c[len_a-1]==0&&lena > 1)
	 lena--;
//至此,删去了高位的0,减法运算结束

3.乘法

      位数          位数          乘完位数
       1             n            n/n+1
       ... 
       i             j            i+j-1/i+j

代码如下(示例):

for (int i = 1 ; i <= len_a ; i++)
    {
        for (int j = 1 ; j <= len_b ; j++)
        {
        /*进行类似加法的操作*/
        c[i+j-1]==c[i+j-1]+s1[i]*s2[j]; 
        c[i+j] += c[i+j-1]/10;
        c[i+j-1] %= 10;
        }
    }

int final_len=0;
final_len=len_a+len_b;
//多一位的情况用以下方式处理
//删去前导的0
while(c[final_len]==0&&final_len > 1)
	 lena--;

4.除法

—日后来补充(

总结

借鉴一些文章,只是作为做题记录,侵删。
洛谷
【入门3】循环结构
P1009 [NOIP1998 普及组] 阶乘之和

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值