版权声明:--(●'◡'●)-- --(●ˇ∀ˇ●)-- https://blog.csdn.net/qq_36032149/article/details/84899575
刚才看到群里一哥们前端计算小数时失去精度,正好在看算法,顺道想了一下解决办法。
现在只有一个进位标志c, 减法再加个借位标志符,差不多的逻辑。
public class Main {
public static void main(String[] args) {
// write your code here
System.out.println(new Main().floatAdd("123.4", "3211")[0]);
}
/**
* 整数相加
*
* @param a 加数 a
* @param b 加数 b
* @return 和 [结果,进位](为了方便浮点数小数部分计算时获取到进位,把结果和进位一起返回)
*/
public String[] intAdd(String a, String b) {
if (a == null || a.trim().equals("")) a = "0";
if (b == null || b.trim().equals("")) b = "0";
int aLen = a.length() - 1;
int bLen = b.length() - 1;
int c = 0;
StringBuilder sb = new StringBuilder(aLen + bLen);
while (aLen >= 0 && bLen >= 0) {
c = cal(a.charAt(aLen--) - '0', b.charAt(bLen--) - '0', c, sb);
}
while (aLen >= 0) {//如果第一个数还有剩余
c = cal(a.charAt(aLen--) - '0', c, c, sb);
}
while (bLen >= 0) {//如果第二个数还有剩余
c = cal(b.charAt(bLen--) - '0', c, c, sb);
}
//if (c > 0) {//如果最后还有进位,添加到最高位
// sb.append(c);
//}
//return sb.reverse().toString();
return new String[]{sb.reverse().toString(), String.valueOf(c)};
}
//例如"1234" + "391" ===>
//1. 4 + 1 + 0 = 5 个位 = 5, 十位 = 0, sb.append(5) ===> result = "5", 进位c = 0
//2. 3 + 9 + 0(上次的进位) = 12 个位 = 12 % 10 = 2, 十位 = 12 / 10 = 1, sb.append(2) ===> result = "52", 进位c = 1
//3. 2 + 3 + 1(上次的进位) = 6 个位 = 6 % 10 = 6, 十位 = 6 / 10 = 0, sb.append(6) ===> result = "526", 进位c = 0
//4. 第一个数还有剩余,循环把最后剩余的数添加进去,但考虑到之前还有进位c, 所以和上述相同操作(把c当作另一个加数)
//因为字符串添加顺序是往后添加,所以最后倒序输出。
/**
* 字符串的单个字符进行运算(这是写完之后把重复的提取出来,抽象出来的公共步骤,所以返回进位这里直接看不好理解)
*
* @param a 加数
* @param b 加数
* @param c 上次的进位
* @param sb 保存结果的地方
* @return 这次的进位
*/
private int cal(int a, int b, int c, StringBuilder sb) {
int sum = a + b;//求和
int _one = sum % 10;//个位
int _ten = sum / 10;//十位
int _sum = _one + c;//这次的和(个位数+上一次的进位)
sb.append(_sum % 10);//这次的 求和 的个位数
c = _sum / 10 + _ten;//这次相加的进位
return c;
}
/**
* 浮点数相加
* 将浮点数分为整数和小数部分 分别相加
* 小数部分的进位再和整数部分相加
* 得到最终结果
* @param a 加数
* @param b 加数
* @return 结果
*/
public String floatAdd(String a, String b) {
String[] ass = a.split("\\.");
String[] bss = b.split("\\.");
String f1 = null, f2 = null;
String z1 = ass[0];
String z2 = bss[0];
if (ass.length > 1) {//如果a有小数
f1 = ass[1];
}
if (bss.length > 1) {//如果b有小数
f2 = bss[1];
}
String[] zs = intAdd(z1, z2);//整数部分求和
String z = zs[0];
if (!zs[1].equals("0")) {//如果最后还有进位,添加到最高位
z = zs[1] + z;
}
String[] fs = intAdd(f1, f2);//小数部分求和
String f = fs[0];
if (!fs[1].equals("0")) {//对进位进行处理
String[] rs = intAdd(zs[0], fs[1]);//小数部分的进位和整数部分相加
if (!rs[1].equals("0")) {//如果最后还有进位,添加到最高位
rs[0] = rs[1] + rs[0];
}
return rs[0] + "." + f;
}
return z + "." + f;
}
}