挑选数值求和使之最接近给定的值

文章提供了一个Java实现的蒙特卡洛组合法算法,用于从一组不同面额的发票中选择若干张,使得它们的面额总和最接近给定的报销金额。代码通过随机选取和检查不同组合,找到最接近目标值的发票组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:最近接到一个需求,要求对当月的发票进行运算,当月有10张发票,每张面额,300-500不等,报销金额是1200,要求从这些发票中选出几张求和最接近1200,用来报销使用。

既:300,350,330,410,366,369,380,371.34,361.25,使用算法挑选几个数字求和,使该数字最接近1200.

技术方案:蒙特卡洛组合法。

代码如下:

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.codehaus.jettison.json.JSONObject;

import com.google.gson.JsonObject;

import net.sf.json.JSONArray;

public class mtkl {

    public ArrayList<Double> MC_combination(ArrayList<Double> nums,double target)
    {
        ArrayList<Double> res = new ArrayList<>();
        double lapse = 10000;
        Random random = new Random();

        for (int i=0;i<1000000;i++)
        {
      
            int numsize = random.nextInt(nums.size()  + 1);
            ArrayList<Double> ares = new ArrayList<>();
            HashMap<Integer,Integer> map = new HashMap<>();
            double thissum = 0;
            for (int j=0 ;j<numsize;j++)
            {
                int anumberindex = random.nextInt(nums.size());
                while (map.containsKey(anumberindex))
                {
                    anumberindex = random.nextInt(nums.size());
                }
                map.put(anumberindex,1);
                ares.add(nums.get(anumberindex));
                thissum += nums.get(anumberindex);
            }
            if(Math.abs(thissum - target)<lapse)
            {
                lapse = Math.abs(thissum - target);
                res = ares;
            }
            if(lapse<0.000001)
                break;
        }
        return res;
    }
    /**
     * 蒙特卡洛组合法
     * 烟雨江南---
     * @param nums
     * @param target
     * @return
     */
    public String getGreatValue(List<Map<String,Object>> list,String amountout){  
        
        JSONObject result=new JSONObject();
        try{
            double target=Double.parseDouble(amountout);
            double lapse = 1000;
            Random random = new Random();
            for (int i=0;i<1000000;i++) {
            int numsize = random.nextInt(list.size()  + 1);
            List<Map<String,Object>> ares = new ArrayList<Map<String,Object>>();
            HashMap<Integer,Integer> map = new HashMap<>();
            double thissum = 0;
            for (int j=0 ;j<numsize;j++){
                int anumberindex = random.nextInt(list.size());
                while (map.containsKey(anumberindex))
                {
                    anumberindex = random.nextInt(list.size());
                }
                map.put(anumberindex,1);
                HashMap<String, Object> obj = new HashMap<String,Object>(); 
                obj.put("id", list.get(anumberindex).get("id"));
                obj.put("amount", list.get(anumberindex).get("amount"));
                ares.add(obj);
                thissum += Double.parseDouble(list.get(anumberindex).get("amount").toString());
            }
            if(Math.abs(thissum - target)<lapse){
                lapse = Math.abs(thissum - target);
                result.put("data", JSONArray.fromObject(ares));
                result.put("count", thissum);
                result.put("litter", Math.abs(thissum - target));
            }
            if(lapse<0.000001){
                break;
            }
                
        }
        }catch(Exception e){
            e.printStackTrace();
        }
        
        return result.toString();
    }


    public static void main(String args[]) {

        
          List<Map<String,Object>> res = new ArrayList<Map<String,Object>>();
          Map obj1 = new HashMap<String,Object>(); 
          obj1.put("id", "A");
          obj1.put("amount", "303");
          res.add(obj1);
          Map obj2 = new HashMap<String,Object>(); 
          obj2.put("id", "B");
          obj2.put("amount", "359");
          res.add(obj2);
          Map obj3 = new HashMap<String,Object>(); 
          obj3.put("id", "C");
          obj3.put("amount", "389");
          res.add(obj3);
          Map obj4 = new HashMap<String,Object>(); 
          obj4.put("id", "D");
          obj4.put("amount", "350");
          res.add(obj4);
          Map obj5 = new HashMap<String,Object>(); 
          obj5.put("id", "E");
          obj5.put("amount", "335");
          res.add(obj5);
          Map obj6 = new HashMap<String,Object>(); 
          obj6.put("id", "F");
          obj6.put("amount", "410");
          res.add(obj6);
          System.out.println(new mtkl().getGreatValue(res,"1250"));

    }
};

### 解析 SUM(INCLUDE{[A],[B],[C]:MIN[D]}) 的含义 此函数组合用于特定的数据处理场景,其中 `SUM` 是求和操作符,而 `INCLUDE` 则是一个假设性的结构化表达方式来指示哪些列应该被纳入计算范围。具体来说: - **SUM**:表示对指定范围内数值进行累加求和的操作[^1]。 - **INCLUDE{}**:这里并非标准 Excel 或数据库查询中的正式语法,而是用来形象描述一种逻辑上的选择机制,即从给定字段 `[A], [B], [C]` 中选取符合条件的记录,并考虑条件 `MIN[D]`。 对于这种形式的理解可以分解如下: #### 对于 A, B 和 C 列的选择 当提到 `INCLUDE{[A],[B],[C]}` 部分时,意味着公式会遍历这三列数据并对其进行评估以决定是否将其加入到求和的过程中去[^2]。 #### 结合 MIN(D) 条件的应用 `:MIN[D]` 表达了一个筛选条件——仅当某行对应的 D 列小的时候才允许该行其他各列(这里是 A、B 及 C)参与后续运算。换句话说,在每一组具有相同特征的数据集中只挑选出那个拥有低 D 的那一行来进行求和操作[^3]。 ```sql SELECT SUM(CASE WHEN t.D = (SELECT MIN(sub.D) FROM table_name sub WHERE sub.key_column = t.key_column GROUP BY sub.key_column) THEN COALESCE(t.A,0)+COALESCE(t.B,0)+COALESCE(t.C,0) ELSE 0 END) FROM table_name t; ``` 上述 SQL 查询语句展示了如何实现类似的逻辑:通过子查询找到每组内的小D并与当前行比较;如果相等,则将对应行的 A+B+C 加入总和中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值