Java实现N元⼀次⽅程组求解
求解n元1次⽅程组
嘴唇有痣⼀:前⾔
公司最近有⼀个项⽬,要求求出煤炭配⽐。⼤意如下:不同煤炭供应商的枚的规格参数是不⼀致的(低位发热量、硫分、全⽔、挥发分、灰分、单价等),现有多家供应商,客户可以输⼊⾃⼰需要的煤炭总量、价格以及参数等,然后得出各家供应商的煤炭对应的配⽐。虽然该部分不是⾃⼰负责,但是感觉⽐较有意思,故⾃⼰也动⼿做了⼀下。
先说下我的思路:假设有3家供应商,A、B、C,配⽐为 x:y:z,那么:
根据单价可以得出 (x A单价 + y B单价+z*C单价)/(x+y+z) = 客户输⼊的单价
根据灰分可以得出 (x A灰分 + y B灰分+z*C灰分)/(x+y+z) = 客户输⼊的灰分
那么不同的参数可以得出⼀个等式,那么此题就变成了解N元⼀次⽅程组了。
⼆:实现思路
⼩学解n元⼀次⽅程组的思路即是解决该题的思路,那么怎么把这个过程⽤代码实现呢。我这⾥先拿⼆元⼀次⽅程举例。⽅程:
x+2y=3;2x−2y=0;
第⼀步:这是两个等式,我⽤数组与键值对的⽅式来存储等式中的元素,即
[{"x":1,"y":2,"=":3},{"x":2,"y":2,"=":0}]
并把要求的元素记录到map中。
第⼆步:消元,找出要消去的元素,⽐如要消去x,那么需要先找到两个等式中x的系数,此时系数为1和2,那么第⼀个系数为1的要乘以2。两个等式相减得 6y = 6。锅盔馍
第三步:将得到的值,带⼊等式,得到另⼀组等式。重复第⼆、三步,即可得到最终的解。
三:n元⼀次⽅程组代码实现
import bean.BeanUtil;
import ollection.CollectionUtil;
import com.alibaba.fastjson.JSON;
llect.Lists;
llect.Maps;
slf4j.Slf4j;
import s.lang3.StringUtils;
import org.springframework.util.Asrt;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* 解 n元⼀次⽅程
*/
@Slf4j
public class EquationSolution {
private static final String X ="x";
private static final String Y ="y";
private static final String PLUS ="\\+";
private static final String SUB ="-";
private static final String MUL ="*";
private static final String DIV ="/";
private static final String EQU ="=";
/
**
* 保留位数
*/
private static final int scale =2;
/**
* BigDecimal保留⼩数的⽅式
*/
private static final int ROUND_TYPE = BigDecimal.ROUND_HALF_UP;
/**
* 最终的解
*/
public static Map<String, String> pv = wHashMap();
/**
* 还需要求解的元素
*/
public static Map<String, String> pvForCalculate = wConcurrentMap(); /**
* 已解出来的参数带⼊⽅程式
*/
public static Map<String, String> daiRuMap = wHashMap();
/**
* 是否计算完成标识 true计算完成
*/
public static boolean endFlag =fal;
/**
* 待求⽅程组
跳尸
*/
public static List<Map<String, String>> decoListStatic = wArrayList();
public static void main(String[] args){
//1 2 3 1
// String e1 = "x+y=3";
// String e2 = "2x+3y=8";
// String e3 = "2x+3y=9";
// String e3 = "3x+4y+3z=20";
/
/ String e1 = "x+y+z=6";
// String e2 = "2x+3y+4z=20";
// String e3 = "3x+4y+3z=20";
String e1 ="x+y+z+f=7";
String e2 ="2x+3y-4z+2f=10";
String e3 ="3x+4y+3z+3f=23";
String e4 ="3x+4y+3z-f=19";
// calculate(e1, e2, e3);
calculate(e1, e2, e3, e4);
log.JSONString(pv));
}
public static void expressions){
//解析表达式处理成要计算的模板
decoListStatic =getDeco(expressions);
log.JSONString(decoListStatic));
solution(decoListStatic);
}
private static void solution(List<Map<String, String>> decoList){
if(CollectionUtils.isEmpty(decoList)|| endFlag){
return;
}
int solvedNum =0;
for(Map<String, String> deco : decoList){
if(deco.keySet().size()==2){
//求解
//把求出的值带⼊等式,刷新表达式
reFreshDecoList(decoListStatic);正义论
//重新计算
玻尿酸功效
solution(decoListStatic);
return;
}el if(deco.keySet().size()==1){
solvedNum +=1;
}
}
if(solvedNum == decoListStatic.size()){
log.info("当前循环所有的值已经求出来");
endFlag =true;
省过return;
}
for(String param : pvForCalculate.keySet()){
log.info("要消除的参数是:"+ param);
List<Map<String, String>> decoCopyList = wArrayList();
//求公倍数
List<BigDecimal> coefficients = wArrayList();
for(Map<String, String> deco : decoList){
Map<String, String> decoCopy = wHashMap();
if(deco.keySet().size()>1&& (param)!= null){
coefficients.add(new (param)));
}
decoCopyList.add(decoCopy);
}
if(CollectionUtil.isEmpty(coefficients)){
continue;
}
BigDecimal beiShu =beiShu(coefficients);
//消元后的
List<Map<String, String>> solvedDecoList = wArrayList();
Map<String, String> lastDecoCopy = null;
for(Map<String, String> decoCopy : decoCopyList){
Map<String, String> copy = wHashMap();
(param)!= null){
//乘以倍数
BigDecimal bs = beiShu.divide(new (param)), scale, ROUND_TYPE);
for(String p : decoCopy.keySet()){
decoCopy.put(p,new (p)).multiply(bs).toString());
copy.put(p, (p));
}
if(!CollectionUtils.isEmpty(lastDecoCopy)){
Map<String, String> calculateMap = wHashMap();
for(String pp : pvForCalculate.keySet()){
//消元
//s = s1 - s2
String s ="";
String s1 = (pp);
String s2 = (pp);
if(StringUtils.isBlank(s1)&& StringUtils.isBlank(s2)){
s ="";
}el if(StringUtils.isBlank(s2)){
s = s1;
}el if(StringUtils.isBlank(s1)){
s ="-"+ s2;
s = s.replace("--","");
}el{
}
if(StringUtils.isBlank(s)||new BigDecimal(s).compareTo(BigDecimal.ZERO)==0){
log.info("该参数被消除:"+ pp);
}el{
calculateMap.put(pp, s);
}
}
calculateMap.put(EQU,new (EQU)).subtract(new (EQU))).toString()); solvedDecoList.add(calculateMap);
}
}
lastDecoCopy = wHashMap();
for(String key : copy.keySet()){
三大营养物质lastDecoCopy.put(key, (key));
}
}
solution(solvedDecoList);
}
}
/**
* 公倍数
*
* @return
*/
public static BigDecimal beiShu(List<BigDecimal> coefficients){
BigDecimal res = BigDecimal.ONE;
for(BigDecimal coefficient : coefficients){
res = res.multiply(coefficient);
}
return res;
}
private static void solve(Map<String, String> map){
if(map.size()!=2){
return;
}
String left ="";
String right ="";
String p ="";
for(String p1 : map.keySet()){
if(p1.equals(EQU)){
right = (p1);
}el{
left = (p1);
p = p1;
}
}
String value =new BigDecimal(right).divide(new BigDecimal(left), scale, ROUND_TYPE).toString();
if(StringUtils.(p))){
pv.put(p, value);
daiRuMap.put(p, value);
}el{
Asrt.(p).equals(value),"参数"+ p +"多解");
}
}
/**
* 刷新DecoList 并把daiRuMap缓存清掉
*
* @param decoList
*/
private static void reFreshDecoList(List<Map<String, String>> decoList){
if(CollectionUtils.isEmpty(daiRuMap)){
return;
}
for(String daiRu : daiRuMap.keySet()){
if(StringUtils.(daiRu))){
for(Map<String, String> deco : decoList){
if(deco.size()<=1){
continue;
}
BigDecimal value =new (daiRu)).multiply(new (daiRu))); BigDecimal subtract =new (EQU)).subtract(value);
deco.put(EQU, String());
if(deco.size()==1){
Asrt.isTrue(pareTo(new (EQU)))==0,"该⽅程组⽆解");
}
}
//把当前的值去掉下次就不做该参数的替换了
}
}
log.JSONString(decoList));
}
private static List<Map<String, String>>getDeco(String[] expressions){
List<Map<String, String>> deco = wArrayList();
for(String expression : expressions){
String[] split = expression.split(EQU);
Asrt.isTrue(split.length ==2,"请检查表达式:"+ expression +"是否正确");
Map<String, String> exMap = wHashMap();
exMap.put(EQU, split[1]);
String[] splitPlus = split[0].replace(SUB,"+-").split(PLUS);
putToExMap(exMap, splitPlus);
deco.add(exMap);
}
return deco;
}
/**
* 2x
* -2x
* +2x
*
* @param es
* @return
*/
public static void putToExMap(Map<String, String> exMap, es){
for(String e : es){
char[] chars = e.toCharArray();
String param ="";
for(char c : chars){
if(97<= c && c <=122){
param =new String(new char[]{c});
人事厅
pv.put(param,"");
pvForCalculate.put(param,"");
}
}
if(StringUtils.isNotBlank(param)){
e = e.replace(param,"");
ains("-")&& StringUtils.place("-",""))){
e ="-1";
}
}
if(StringUtils.place("-",""))){