博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
大数运算(1)—— 加法篇
阅读量:5046 次
发布时间:2019-06-12

本文共 1547 字,大约阅读时间需要 5 分钟。

 前言

  最近遇到一道求阶乘的题目,原以为极其简单,但是阶乘的结果超过了范围最大的基本数据类型的范围,于是就着手研究大数运算(large number computing),本篇先介绍大数加法。

原理

  大数运算的原理其实就是模拟人工计算(注记:再考虑是否有其他算法。注记日期:2017.3.19),人工加法计算步骤如下:

    1.将两个操作数(operand)位数对齐。

    2.从最低位开始,计算两个操作数每位的总和再加上进位数(第一位数为0)的结果,保留其个位数。

    3.若上述的结果大于10,进位数置为1,否则为0。(每位数相加的结果不会超过 9 + 9 = 18 , 因此进位数只有1和0)

    4.重复上述步骤2、3,直到计算完两个操作数其中那个位数小的最高位。

  知晓了步骤,就需要考虑设计储存操作数的数据结构。首先使用列表是毋庸置疑的,而顺序结构和链表结构其实都行,这里为里减少代码量和说明问题,暂且使用顺序结构

  综上,给出操作数的结构体如下:

1 typedef struct operand2 {3     int data[100];4     int digit;    // 记录该数位数5 } OPERAND;

  注意,这里给出最大位数为100,下面给出的代码中没有考虑溢出问题,请读者自行解决。

实现

  首先,思考上述步骤1的对齐问题,可以定义一个偏移量(offset)来存储两个操作数的位数之差,之后遍历的时候可以给位数少的增加偏移量来达到对齐目的。可是这种做法会增加一定的代码量,因此不妨试着把数字倒着存放,即数组第一个元素存储操作数的最低位(注意前述做法的前提与此相反),这样做就省去了写对齐的代码。

  下面给出该出加法函数,其中结果保存到第一个操作数中

1 void plus(OPERAND* operand1,OPERAND* operand2) 2 { 3     int carry = 0;    // 进位标记 4     int i = 0 , j = 0; 5     for(;i < operand1->digit || j < operand2->digit;i++ , j++) 6     { 7         int sum = operand1->data[i] + operand2->data[j]  8                   + carry;    // 计算该位数总和加上进位数 9         operand1->data[i] = sum % 10;    // 更新该位数的数据10         carry = (sum >= 10)? 1 : 0 ;    // 判断是否进位11     }12     operand1->digit = (operand1->digit > operand2->digit)?13                        operand1->digit : operand2->digit ;14                        // 更新位数15     if(carry)    // 若最后需要进位16     {17         operand1->data[operand1->digit] = 1;18         operand1->digit += 1;19     }20 }

  其中,sum % 10 用于求个位数,还有注意最后别忘了最高位的进位问题。

转载于:https://www.cnblogs.com/linzhehuang/p/6581072.html

你可能感兴趣的文章
AngularJS学习篇(一)
查看>>
【转载】 IP实时传输协议RTP/RTCP详解
查看>>
关于Xshell无法连接centos6.4的问题
查看>>
Linux系统的数据写入机制--延迟写入
查看>>
css3动画——基本准则
查看>>
javaweb常识
查看>>
Java注解
查看>>
时间>金钱
查看>>
元数据元素
查看>>
Visual Studio Code 构建C/C++开发环境
查看>>
web自己主动保存表单
查看>>
一个小的日常实践——高速Fibonacci数算法
查看>>
创建与删除索引
查看>>
java的基本数据类型
查看>>
机器学些技法(9)--Decision Tree
查看>>
静态页面复习--用semantic UI写一个10min首页
查看>>
在Windows下安装64位压缩包版mysql 5.7.11版本的方法
查看>>
drf权限组件
查看>>
输入月份和日期,得出是今年第几天
查看>>
利用mysqldump备份mysql
查看>>