当你计算百分比时,每项的结果按照四舍五入来计算,会有大概率得到的所有结果相加超过 100% 或则小于 100%,比如是 99.99%,100.1% 这样的结果,可以针对此种情况进行修正,思路:找到其中最大的一项,进行修正,因为最大项修正对于结果来说不会有太大的改变,如上所示一般相差结果在 1% 以内。

    下面是具体代码

    1. /**
    2. * 结果修正
    3. * <pre>
    4. * 计算结果由于是四舍五入,可能会导致百分比相加得不到 100,或则会超过 100,需要进行修正
    5. * 修正策略:将占比最高的一项进行修正,多的减少、少的增加,各项相加最终为 100%
    6. * </pre>
    7. *
    8. * @param datas ReportKVDouble 自定义业务对象,其中的 V 字段是四舍五入后的结果项,整个 list v 相加有可能超过或则低于 100%,进行修正
    9. */
    10. private void resultCorrection(List<ReportKVDouble> datas) {
    11. ReportKVDouble max = null;
    12. Double total = 0D;
    13. for (ReportKVDouble data : datas) {
    14. if (max == null) {
    15. max = data;
    16. }
    17. if (data.getV() > max.getV()) {
    18. max = data;
    19. }
    20. total += data.getV();
    21. }
    22. // 如果该项无值,则忽略
    23. if (total == 0) {
    24. return;
    25. }
    26. if (total == 100) {
    27. return;
    28. }
    29. if (total < 100) {
    30. // 需要增加
    31. final double temp = 100D - total;
    32. // 如果值相差 1% , 则直接返回,有可能统计结果就是错误的
    33. // 四舍五入,有小数情况下,不会超过此值
    34. if (temp >= 1) {
    35. return;
    36. }
    37. double newV = add(max.getV(), temp);
    38. max.setV(newV);
    39. } else {
    40. // 需要减少
    41. final double temp = total - 100;
    42. if (temp >= 1) {
    43. return;
    44. }
    45. double newV = sub(max.getV(), temp);
    46. max.setV(newV);
    47. }
    48. }
    49. // cn.hutool.core.util.NumberUtil hutool 中的工具类
    50. /**
    51. * 相加,并保留 1 位小数
    52. *
    53. * @param v1
    54. * @param v2
    55. * @return
    56. */
    57. private double add(Double v1, Double v2) {
    58. return NumberUtil.add(new BigDecimal(v1), new BigDecimal(v2))
    59. .setScale(1, BigDecimal.ROUND_HALF_UP)
    60. .doubleValue();
    61. }
    62. private double sub(Double v1, Double v2) {
    63. return NumberUtil.sub(new BigDecimal(v1), new BigDecimal(v2))
    64. .setScale(1, BigDecimal.ROUND_HALF_UP)
    65. .doubleValue();
    66. }