您的位置:首页 > 其它

高精度整数加法

2017-01-06 14:22 239 查看

题目描述

在计算机中,由于处理器位宽限制,只能处理有限精度的十进制整数加减法,比如在32位宽处理器计算机中,
参与运算的操作数和结果必须在-231~231-1之间。如果需要进行更大范围的十进制整数加法,需要使用特殊
的方式实现,比如使用字符串保存操作数和结果,采取逐位运算的方式。如下:
9876543210 + 1234567890 = ?
让字符串 num1="9876543210",字符串 num2="1234567890",结果保存在字符串 result = "11111111100"。
-9876543210 + (-1234567890) = ?
让字符串 num1="-9876543210",字符串 num2="-1234567890",结果保存在字符串 result = "-11111111100"。

要求编程实现上述高精度的十进制加法。
要求实现方法:
public String add (String num1, String num2)
【输入】num1:字符串形式操作数1,如果操作数为负,则num1的前缀为符号位'-'
num2:字符串形式操作数2,如果操作数为负,则num2的前缀为符号位'-'
【返回】保存加法计算结果字符串,如果结果为负,则字符串的前缀为'-'

注:
(1)当输入为正数时,'+'不会出现在输入字符串中;当输入为负数时,'-'会出现在输入字符串中,且一定在输入字符串最左边位置;
(2)输入字符串所有位均代表有效数字,即不存在由'0'开始的输入字符串,比如"0012", "-0012"不会出现;
(3)要求输出字符串所有位均为有效数字,结果为正或0时'+'不出现在输出字符串,结果为负时输出字符串最左边位置为'-'。


输入描述

输入两个字符串


输出描述

输出给求和后的结果


输入例子

9876543210
1234567890


输出例子

11111111100


算法实现

import java.util.Scanner;

/**
* All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//        Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data2.txt"));
while (scanner.hasNext()) {

String n = scanner.next();
String m = scanner.next();
// 【1】方法一
System.out.println(add(n, m));

// 【2】方法二
//            BigInteger bi1 = new BigInteger(n);
//            BigInteger bi2 = new BigInteger(m);
//            System.out.println(bi1.add(bi2));
}

scanner.close();
}

/**
* 大整数相加,n、m都为自然数
*
* @param ns 数字
* @param ms 数字
* @return 结果
*/
private static String add(String ns, String ms) {

// ns是否为正数
boolean pn = ns.charAt(0) != '-';
// ms是否为正数
boolean pm = ms.charAt(0) != '-';

int[] n;
int[] m;
if (pn) {
n = getNumber(ns);
} else {
n = getNumber(ns.substring(1));
}

if (pm) {
m = getNumber(ms);
} else {
m = getNumber(ms.substring(1));
}

// 两者同号
if (pn == pm) {
// 进行计算
int[] r = add(m, n);
String rs = toNumber(r);

// 根据需要添加负号
if (pn) {
return rs;
} else {
return "-" + rs;
}
} else {
// ns的绝对值比大于等于ms
if (compare(n, m) >= 0) {
int[] r = minus(n, m);
String rs = toNumber(r);
// ns为正数,ms为负数
if (pn) {
return rs;
} else {
return "-" + rs;
}
}
// ns的绝对值比小于ms
else {
int[] r = minus(m, n);
String rs = toNumber(r);

// ns为正数,ms为负数
if (pn) {
return "-" + rs;

} else {
return rs;
}
}
}
}

/**
* 两个整数相加
*
* @param m 整数
* @param n 整数
* @return 结果
*/
private static int[] add(int[] m, int[] n) {

//        System.out.println(Arrays.toString(n) +"\n"+ Arrays.toString(m));

// 保证n不小于m
if (m.length > n.length) {
int[] t = m;
m = n;
n = t;
}

// 结果的最大长度
int[] r = new int[n.length + 1];
// 来自低位的进位
int c = 0;

for (int i = 0; i < m.length; i++) {
r[i] = m[i] + n[i] + c;
c = r[i] / 10;
r[i] %= 10;
}

// 计算余下的部分
for (int i = m.length; i < n.length; i++) {
r[i] = n[i] + c;
c = r[i] / 10;
r[i] %= 10;
}

//        System.out.println(Arrays.toString(n) +"\n"+ Arrays.toString(m) + "\n" + Arrays.toString(r));

// 最后还有进位
if (c != 0) {
r[r.length - 1] = c;
return r;
}
// 没有进位
else {
int[] ret = new int[r.length - 1];
System.arraycopy(r, 0, ret, 0, ret.length);
return ret;
}
}

/**
* 比较两个整数是否相等,下标由小到大表示由低位到高位,忽略最高有效位上的前导0
*
* @param m 整数
* @param n 整数
* @return m > n返回1,m = n返回0,m < n返回-1
*/
private static int compare(int[] m, int[] n) {

if (m == null && n == null) {
return 0;
}
// null最小
if (m == null) {
return -1;
}

if (n == null) {
return 1;
}

int lastM = m.length - 1;
int lastN = n.length - 1;

// 找m的最高有效位的位置,至少有一位
while (lastM >= 1 && m[lastM] == 0) {
lastM--;
}
// 找n的最高有效位的位置,至少有一位
while (lastN >= 1 && n[lastN] == 0) {
lastN--;
}

// m的数位比n多,说明m比n大
if (lastM > lastN) {
return 1;
}
// m的数位比n少,说明m比n小
else if (lastM < lastN) {
return -1;
} else {
// 位数一样,比较每一个数位上的值,从高位到低位进行比较
for (int i = lastM; i >= 0; i--) {
if (m[i] > n[i]) {
return 1;
} else if (m[i] < n[i]) {
return -1;
}
}

return 0;
}
}

/**
* 做减法n-m,保证n大于等于m
*
* @param n 整数
* @param m 整数
* @return 结果
*/
private static int[] minus(int[] n, int[] m) {

n = format(n);
m = format(m);

int[] r = new int[n.length];

// 当前位被借位
int c = 0;
int t;
for (int i = 0; i < m.length; i++) {
t = n[i] - c - m[i];
// 当前位够减
if (t >= 0) {
r[i] = t;
// 没有进行借位
c = 0;
}
// 不够减
else {
r[i] = t + 10;
// 进行借位
c = 1;
}
}

// 还有借位或者n比m位数多,要将n中的数位复制到r中
for (int i = m.length; i < n.length; i++) {
t = n[i] - c;
// 当前位够减
if (t >= 0) {
r[i] = t;
// 没有进行借位
c = 0;
}
// 不够减
else {
r[i] = t + 10;
// 进行借位
c = 1;
}
}

return format(r);
}

/**
* 将整数字符串表示成整数数组【包含符号位】
*
* @param n 整数字符串
* @return 整数数组 下标从小到大表示数位的从低到高
*/
private static int[] getNumber(String n) {
int[] r = new int[n.length()];
for (int i = 0; i < r.length; i++) {
r[i] = n.charAt(n.length() - i - 1) - '0';
}

return r;
}

/**
* 将整数进行格式化,去掉高位的前导0
*
* @param r 整数
* @return 结果
*/
private static int[] format(int[] r) {
int t = r.length - 1;
// 找最高有效位
while (t > 0 && r[t] == 0) {
t--;
}

int[] nr = new int[t + 1];
System.arraycopy(r, 0, nr, 0, nr.length);
return nr;

}

/**
* 将数组表示的整数转换成字符串
*
* @param r 整数
* @return 字符串表示的整数
*/
private static String toNumber(int[] r) {
if (r == null) {
return null;
}

StringBuilder b = new StringBuilder(r.length);

for (int i = r.length - 1; i >= 0; i--) {
b.append(r[i]);
}

return b.toString();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: