数字字符串运算

版权声明:--(●'◡'●)-- --(●ˇ∀ˇ●)-- 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;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36032149/article/details/84899575