作者chchwy (mat)
看板NTUE-CS100
标题Re: [课业] 大数运算
时间Mon Dec 29 07:22:38 2008
目标二: public BigNum add ( BigNum input ) {} //加法
都是国中程度的数学,不过还是复习一下XD
科学记号做加法有两个步骤
a、指数先化为相同
b、再对假数做加法运算
我举个例子,怎麽做 1.002 * 10^2 + 2.0003 * 10^3 = ?
a. 先将1.002*10^2 =转成=> 0.1002*10^3 (指数相同)
b. 0.1002 + 2.0003 = 2.1005 (指数对齐後,假数相加)
答案 = 2.1005 * 10^3 对吧?
转换成程式想法,有三件事要做
1. 找出两个数的次方差d
2. 小的次方加上d,让两数次方相等
3. 比较小的假数前面补上d个0 (为了维持正规化)
用上面的例子
1.求次方差 d = 3-2 = 1
2.都设成3次方
2.假数1002前面加上d个零,也就是1个零 => 01002
然後就可以开始做假数加法了
这时候!! 我们搬出国小那套直式加法,将将 ( ̄▽ ̄#)﹏﹏
从最小位开始 (也就是字串末端)
然後一位一位依序加上去。
这里我们要让m1跟m2这两个假数相加,然後结果存到mSum里去
<-----------这个方向加
1 <=(进位)
m1: 20093
+ m2: 1001
------------------
mSum: 30103
依照这个想法,把字元一个一个抽出来相加就行了。
//来看程式码,我们要做的是this(自己)跟input相加
public BigNum add(BigNum input){
//小地方注意,加法必须两数同号才行
// 例如(-5)+3表面上是加法,其实骨子里根本就是减法
//
if(this.sign!=input.sign){
//应该呼叫减法....
}
//----做次方对齐----
int dif = this.exp - input.exp; //先求次方差
BigNum smaller;
if(dif<0) smaller = this; //this.exp比较小
else smaller = input; //input.exp比较小
dif = Math.abs(dif); //dif取绝对值
smaller.exp += dif; //让两数次方对齐
for(int i=0;i<dif;++i) //填零
smaller.mantissa.insert(0, '0');
//---对齐工作结束---
//----假数相加------
/*
这里我们要让m1跟m2这两个假数相加,然後结果存到mSum里去
====简单加法演算法========
for (i = 字串尾 to 字串头){
sum = m1 的第 i 位 + m2 的第 i 位 + 前一次的进位;
sum = n % 10;
进位 = n / 10;
sum写进mSum里;
}
===========================
有个小地方要注意,两个假数长度不一定相同,
若超出字串长度就设定成加零。
m1: 2.0093
m2: 1.002 <=这里有个隐含0,不然3要跟谁相加?
*/
StringBuffer m1 = this.mantissa;
StringBuffer m2 = input.mantissa;
StringBuffer mSum = new StringBuffer("");
//找出比较长的字串,当成字串尾
int max = Math.max( m1.length(), m2.length() );
int carry=0; //carry拿来纪录进位值
for(int i=max-1;i>=0;--i){ //从字串尾端开始往前一位一位加
int sum, num1, num2;
//第i位抽出来,分别放进num1跟num2里面
//超出范围就设成零
if(i<m1.length()) num1 = m1.charAt(i) - '0';
else num1=0;
if(i<m2.length()) num2 = m2.charAt(i) - '0';
else num2=0;
sum = num1 + num2 + carry; //两数相加,别忘了前一次产生的进位
carry = sum/10; //取出十位数当做进位
sum = sum%10; //留下个位数
mSum.insert(0, sum); //把结果塞进mSum里
}
if(carry>0){ //如果最後还剩一个进位
mSum.insert(0, carry); //塞进去mSum
exp++; //正规化
}
//设定结果,只要改mantissa,sign跟exp都不用动
this.mantissa = mSum;
return this;
}
Good! 加法完成
测试一下
123.456 + 876.543
9999.9 + 0.1
100.001 + 100.999
看看结果如何?
如果加法完全了解,那减法也八九不离十了。
下一篇我会直接讲乘法~
--
怀着一颗对这个家有无限关爱的心,我,再度流浪到远方。 --<舒伯特>
这些年来,我唱着歌,唱出爱,可是它对我来说却是痛苦;
我唱出痛苦,可是它对我来说又是爱。 爱与痛苦就这样分割着我。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 203.68.15.209
※ 编辑: chchwy 来自: 203.68.15.209 (12/29 05:06)
1F:推 bearNturtle:感谢!!! 12/29 05:16
※ 编辑: chchwy 来自: 203.68.15.209 (12/29 06:40)