一、主要目的
模拟实现两个很大的数之间进行加法;
二、主要思路
1、把两个数当做字符串存放到内存里;
2、从后面开始遍历这两个字符串;
3、把对应位置的字符,转成单个整数,然后相加,判断是否出现进位;
4、没有进位就直接保存在结果里;有进位需要处理进位;
三、代码如下
(一)相加类
/**
* 模拟相加和移位运算
*/
public class CPU {
/**
* 模拟十进制整数之间的加法
* 每一位相加,进行进位;
*
*
* @param left
* @param right
*/
public static void add(String left, String right){
if (left != null && right != null) {
if (isCorrect(left) && isCorrect(right)) {
// 首先向右对齐才能计算
// 如果两个数字位数不相等,就进行填充数字0进行相等;
if (left.length() != right.length()) {
if (left.length() > right.length()) {
StringBuffer buffer = new StringBuffer(right);
buffer.insert(0, getZeros(left.length() - right.length()));
right = buffer.toString();
} else {
StringBuffer buffer = new StringBuffer(left);
buffer.insert(0, getZeros(right.length() - left.length()));
left = buffer.toString();
}
}
System.out.println("left:" + left.toString());
System.out.println("right:" + right.toString());
// 定义存放结果的缓冲(填充相同位数的0)
StringBuffer result = new StringBuffer(getZeros(left.length()));
int v1,v2,v3;
int temp = 0;
// 从右边开始,遍历两个字符串的每一位字符
for (int k = left.length() - 1; k >= 0; k--) {
// 获得字符的数字代表的整数,例如ASCII字符'1'的字节值减去48后等于1
v1 = left.charAt(k) - 48;
v2 = right.charAt(k) - 48;
v3 = result.charAt(k) - 48;
// 计算某一位的相加值
temp = v1 + v2 + v3;
// 如果大于9,需要往高位进1
if (temp > 9) {
result.setCharAt(k, (char)((temp % 10) + 48));
// 把进位1设置在result字符串里
carry(result, left.length() - k + 1);
} else {
result.setCharAt(k, (char)(temp + 48));
}
}
System.out.println("加法计算结果为:" + result.toString());
} else {
throw new IllegalArgumentException("not digit calculation.");
}
}
}
/**
* 处理字符的进位
* 进位规则:
* 从右边依次将每一位进行计算,转成数字后,相加后的结果,如果超过10就进1;
* 例如:5 + 6 = 11 ,那么向前加一,当前位是1;
* 需要把这进位的1,加到前面;
* @param result 目标结果的字符
* @param index 需要加一的位置;从右侧开始编号,第一位是1;
*/
public static void carry(StringBuffer result, int index) {
// 1、如果位数不够,需要在前面填充0
if (result.length() < index){
result.insert(0, '0');
}
// 2、获得需要进位的数字的整型值
int digit = result.charAt(result.length() - index) - 48;
// 3、数字加一
digit = digit + 1;
// 4、如果超过9,需要给前面的数字进一
if (digit > 9){
// 4.1、获得余数
int leaving = digit % 10;
// 4.2、给当前位设置为余数
result.setCharAt(result.length() - index, (char)(leaving + 48));
// 4.3、给前面的位数加一
carry(result, index + 1);
} else {
// 5、直接设置当前位
result.setCharAt(result.length() - index, (char)(digit + 48));
}
}
/**
* 返回想要的数字0组成的字符串
* @param num 个数
* @return 字符串
*/
public static String getZeros(int num){
StringBuffer result = new StringBuffer();
for (int k = 1; k <= num; k++) {
result.append("0");
}
return result.toString();
}
/**
* 判断数字是否正确
* @param digit
* @return
*/
public static boolean isCorrect(String digit){
boolean isCorrect = true;
if (digit != null && digit != "") {
char t = ' ';
// 如果出现一个字符不是数字,就返回不正确
for (int i = 0; i < digit.length(); i++) {
t = digit.charAt(i);
if (t < '0' || t > '9'){
isCorrect = false;
break;
}
}
} else {
isCorrect = false;
}
return isCorrect;
}
}
(二)测试类
public class Test{
public static void main(String[] args) {
System.out.println("模拟加法:");
CPU.add("655555555555555566666884422214555545555120", "434353535353553534280");
}
}
四、测试结果如下
五、总结
1、大数相加已经超出long类型变量的存储范围。
2、需要用字符串来存储,甚至使用磁盘文件来存放位数很大的整数或者小数;