double计算丢失精度问题解决

涉及到double算法的时候,调用下面的放下就可以了

算法:加减乘除


    //加
    public static Double addToDouble(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    //减
    public static double subToDouble(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    //乘
    public static double mul(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /***
     * 功能描述: 除
     * 〈〉
     * @Param: [v1, v2, scale表示表示需要精确到小数点以后几位]
     * @Return: double
     * @Author: by 
     * @Date: 2019/12/19 11:04
     */
    public static double divToDouble(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

例子:

            LocalDateTime cacheDay = null;
            Double dailyCapability = 0.0;
            Double availableCapability = 0.0;
            Double beUsedCapability = 0.0;
            Map<String, Map<String, Double>> sboxesInfoMap = new HashMap<>();
            cacheDay = statMap.getDay();
            //筛选满足某天统计有产能产出的sboxes
            List<SBox> statSboxes = filterSboxesByDaily(sboxes, cacheDay, craftHours);
            if (CollectionUtils.isEmpty(statSboxes)) {
                //logger.warn("流水线:{},日期:{} 没有产能",slineId,cacheDay.toString());
                continue;
            }
            for (SBox statSbox : statSboxes) {
                HashMap<String, Double> boxInfo = new HashMap<>();
                Double outPutCapabilitySboxDaily = 0.0;
                Double percent = calcSboxCapabilityPercent(statSbox, cacheDay, craftHours);
                percent = conversionDecimal(percent);//4位小数
                outPutCapabilitySboxDaily = mul(statSbox.getCapability(),percent);
                dailyCapability = addToDouble(dailyCapability,outPutCapabilitySboxDaily);
                boxInfo.put("total", outPutCapabilitySboxDaily);//sbox某天总产能
                if (statSbox.getUseState() == UseStateEnum.ALL_BE_USED.getCode()) {
                    //todo 情况:useStatus==3  产能分在两天,1=8000,2=3000,pre=1560,last=200  需要字段承载boxinfo:used,ava,total,forget
                    beUsedCapability = addToDouble(beUsedCapability,outPutCapabilitySboxDaily);
                    boxInfo.put("ava", 0.0);//sbox某天可用产能
                    if (!StringUtils.isEmpty(statSbox.getPreUseCapability()) && !StringUtils.isEmpty(statSbox.getLastUseCapability())) {
                        Double boxUsedCapa = addToDouble(statSbox.getPreUseCapability(),statSbox.getLastUseCapability());
                        //boxInfo.put("used", boxUsedCapa);//sbox某天被占用产能
                        Double passCapa = queryPassDaySboxCapa(statSbox, cacheDay, craftHours);
                        Double reqCapability = subToDouble(boxUsedCapa,passCapa);
                        if (reqCapability>0){ //占用的值大于0
                            if (reqCapability <= outPutCapabilitySboxDaily){//占用的值小于今天的产出
                                boxInfo.put("used", reqCapability);
                            }else { //占用的值大于今天的产出
                                boxInfo.put("used", outPutCapabilitySboxDaily);
                            }
                        }else {
                            boxInfo.put("used", 0.0);
                        }
                    } else {
                        boxInfo.put("used", outPutCapabilitySboxDaily);//sbox某天被占用产能
                    }
                } else if (statSbox.getUseState() == UseStateEnum.PRE_USED.getCode()) {
                    // 这天之前,sbox产能是否已经被分配了部分
                    //Double passUsedCapa = queryPassUsedPreCapability(slineId, cacheDay, statSbox.getStreamBoxId());
                    Double passUsedCapa = queryPassDaySboxCapa(statSbox, cacheDay, craftHours);
                    Double PreReqCapability = subToDouble(statSbox.getPreUseCapability(),passUsedCapa);
                    if (PreReqCapability <= 0) {
                        availableCapability = addToDouble(availableCapability,outPutCapabilitySboxDaily);
                        boxInfo.put("ava", outPutCapabilitySboxDaily);
                        boxInfo.put("used", 0.0);
                    } else {
                        //前半部分产能被占用
                        if (PreReqCapability >= outPutCapabilitySboxDaily) {
                            beUsedCapability = addToDouble(beUsedCapability,outPutCapabilitySboxDaily);
                            boxInfo.put("ava", 0.0);
                            boxInfo.put("used", outPutCapabilitySboxDaily);
                        } else if (PreReqCapability < outPutCapabilitySboxDaily) {
                            Double beUse = PreReqCapability;
                            Double canUse = subToDouble(outPutCapabilitySboxDaily,beUse);
                            beUsedCapability = addToDouble(beUsedCapability,beUse);
                            availableCapability = addToDouble(availableCapability,canUse);
                            boxInfo.put("ava", canUse);
                            boxInfo.put("used", beUse);
                        }
                    }
                } else if (statSbox.getUseState() == UseStateEnum.LAST_USED.getCode()) {//测试通过
                    // 这天之后,sbox还有多少产出
                    Double laterCapa = queryLaterDaySboxCapa(statSbox, cacheDay, craftHours);
                    Double laterReqCapability = subToDouble(statSbox.getLastUseCapability(),laterCapa); //还需要多少
                    //后半部分产能被占用
                    if (laterReqCapability <= 0) {
                        availableCapability = addToDouble(availableCapability,outPutCapabilitySboxDaily);
                        boxInfo.put("ava", outPutCapabilitySboxDaily);
                        boxInfo.put("used", 0.0);
                    } else {
                        if (laterReqCapability >= outPutCapabilitySboxDaily) {
                            beUsedCapability = addToDouble(beUsedCapability,outPutCapabilitySboxDaily);
                            boxInfo.put("ava", 0.0);
                            boxInfo.put("used", outPutCapabilitySboxDaily);
                        } else if (laterReqCapability < outPutCapabilitySboxDaily) {
                            Double beUse = laterReqCapability;
                            Double canUse = subToDouble(outPutCapabilitySboxDaily,beUse);
                            beUsedCapability =addToDouble(beUsedCapability,beUse);
                            availableCapability = addToDouble(availableCapability,canUse);
                            boxInfo.put("ava", canUse);
                            boxInfo.put("used", beUse);
                        }
                    }
                } else if (statSbox.getUseState() == UseStateEnum.CAN_USED_ALL.getCode()) {
                    availableCapability = addToDouble(availableCapability,outPutCapabilitySboxDaily);
                    boxInfo.put("ava", outPutCapabilitySboxDaily);
                    boxInfo.put("used", 0.0);
                }
                //灰色,不可用/抛弃的的产能
                boxInfo.put("forget", subToDouble(outPutCapabilitySboxDaily,addToDouble(boxInfo.get("ava"),boxInfo.get("used"))));
                sboxesInfoMap.put(statSbox.getStreamBoxId(), boxInfo);
            }
            statMap.setAvailableCapability(availableCapability);
            statMap.setBeUsedCapability(beUsedCapability);
            statMap.setDailyCapability(dailyCapability);
            statMap.setSboxesInfoMap(sboxesInfoMap);
发布了109 篇原创文章 · 获赞 2 · 访问量 5701

猜你喜欢

转载自blog.csdn.net/Seven71111/article/details/103610976
今日推荐