Skip to content

Commit

Permalink
优化了equation模块化简部分的问题,使化简更充分
Browse files Browse the repository at this point in the history
  • Loading branch information
XiaoXueTu555 committed May 7, 2023
1 parent 269ac74 commit 458a285
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 16 deletions.
115 changes: 105 additions & 10 deletions SeekAnAnswer/SeekAnAnswer/kernel/equation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,19 +664,25 @@ void Equation::linear_equation_with_one_unknown()

this->root1.b = this->coefficient_left.at(this->FindDegree(degree));

//如果分母是整数,则化简
if (root1.b.IsNumber() && root1.b.list.at(0).GetCoefficient().b == 1)
if (this->root1.a.IsNumber() && this->root1.a == Polynomial("(0/1)"))
{
root1.a *= (Monomial)(Fraction<sint64>(1, root1.b.list.at(0).GetCoefficient().a));
this->root1.b.list.at(0).SetCoefficientA(1);
this->root1.b = Polynomial("(1/1)");
return;
}

//如果分母是纯数字分式,则化简
else if (root1.b.IsNumber() && root1.b.list.at(0).GetCoefficient().b != 1)
{
root1.a *= (Monomial)(Fraction<sint64>(root1.b.list.at(0).GetCoefficient().b, 1));
this->root1.b.list.at(0).SetCoefficientB(1);
}
//最小公倍数
Fraction<sint64> least_common_multiple =
this->root1.a.LeastCommonMultiple_of_coe(this->root1.b);

this->root1.a *= Monomial(least_common_multiple);
this->root1.b *= Monomial(least_common_multiple);

//求分子与分母的公因式
Monomial common_factor = this->root1.a.CommonFactor(this->root1.b);
//分别除以公因式以化简
this->root1.a /= common_factor;
this->root1.b /= common_factor;

//如果分母的分式的分子是-1,则化简
if (root1.b.IsNumber() && root1.b.list.at(0).GetCoefficient().a == -1)
{
Expand Down Expand Up @@ -770,6 +776,26 @@ void Equation::quadratic_equation_in_one_unknown()
this->root2.at(i).b = Polynomial_Exponential_Sum(Polynomial_Exponential(Fraction<sint64>(1, 1),
Polynomial(Monomial("(1/1)")), Fraction<sint64>(1, 1)));
}
//如果分子不为0,则约分
if ((Polynomial)this->root2.at(i).a != Polynomial("(0/1)"))
{
//求最小公倍数
Fraction<sint64> LeastCommonMultiple =
((Polynomial)this->root2.at(i).a).LeastCommonMultiple_of_coe((Polynomial)this->root2.at(i).b);

this->root2.at(i).a =
(Polynomial_Exponential)(((Polynomial)this->root2.at(i).a) * Monomial(LeastCommonMultiple));

this->root2.at(i).b =
(Polynomial_Exponential)(((Polynomial)this->root2.at(i).b) * Monomial(LeastCommonMultiple));

//求最大公约数
Monomial common_factor =
((Polynomial)this->root2.at(i).a).CommonFactor((Polynomial)this->root2.at(i).b);

this->root2.at(i).a = (Polynomial_Exponential)(((Polynomial)this->root2.at(i).a) / common_factor);
this->root2.at(i).b = (Polynomial_Exponential)(((Polynomial)this->root2.at(i).b) / common_factor);
}
}
else if (this->root2.at(i).a.IsPolynomial_Exponential()
&& this->root2.at(i).b.IsPolynomial_Exponential())
Expand All @@ -783,6 +809,75 @@ void Equation::quadratic_equation_in_one_unknown()
Polynomial(Monomial("(1/1)")), Fraction<sint64>(1, 1)));
}
}

//提出系数,为下面化简做准备
this->root2.at(i).a.Split();
this->root2.at(i).b.Split();

//如果系数不为0
if (this->root2.at(i).a.list.at(0).coefficient != Fraction<sint64>(0, 1))
{
std::vector<sint64> a; Fraction<sint64> temp_a(1, 1);
std::vector<sint64> b;
//获取公倍数
for (suint64 j = 0; j < this->root2.at(i).a.list.size(); j++)
{
a.push_back(this->root2.at(i).a.list.at(j).coefficient.b);
temp_a.a *= a.at(a.size() - 1);
}
for (suint64 j = 0; j < this->root2.at(i).b.list.size(); j++)
{
a.push_back(this->root2.at(i).b.list.at(j).coefficient.b);
temp_a.a *= a.at(a.size() - 1);
}

//乘以最小公倍数
for (suint64 j = 0; j < this->root2.at(i).a.list.size(); j++)
{
//分子乘以公倍数
this->root2.at(i).a.list.at(j).coefficient =
this->root2.at(i).a.list.at(j).coefficient *
(temp_a / Fraction<sint64>(Fraction<sint64>::gcds(a), 1));
}
for (suint64 j = 0; j < this->root2.at(i).b.list.size(); j++)
{
//分母乘以公倍数
this->root2.at(i).b.list.at(j).coefficient =
this->root2.at(i).b.list.at(j).coefficient *
(temp_a / Fraction<sint64>(Fraction<sint64>::gcds(a), 1));
}


//获取公因数
for (suint64 j = 0; j < this->root2.at(i).a.list.size(); j++)
{
b.push_back(this->root2.at(i).a.list.at(j).coefficient.a);
}
for (suint64 j = 0; j < this->root2.at(i).b.list.size(); j++)
{
b.push_back(this->root2.at(i).b.list.at(j).coefficient.a);
}

//除以最大公约数
for (suint64 j = 0; j < this->root2.at(i).a.list.size(); j++)
{
//分子除以公约数
this->root2.at(i).a.list.at(j).coefficient =
this->root2.at(i).a.list.at(j).coefficient /
Fraction<sint64>(Fraction<sint64>::gcds(b), 1);
}
for (suint64 j = 0; j < this->root2.at(i).b.list.size(); j++)
{
//分母除以公约数
this->root2.at(i).b.list.at(j).coefficient =
this->root2.at(i).b.list.at(j).coefficient /
Fraction<sint64>(Fraction<sint64>::gcds(b), 1);
}
}

//将系数合并回底数
this->root2.at(i).a.Merge();
this->root2.at(i).b.Merge();
}
return;
}
Expand Down
11 changes: 10 additions & 1 deletion SeekAnAnswer/SeekAnAnswer/kernel/fraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,9 @@ class Fraction <sint64>
}
public:
/*欧几里得算法*/
sint64 gcd(sint64 a, sint64 b)
static sint64 gcd(sint64 a, sint64 b)
{
a = abs(a); b = abs(b);
sint64 mod = a % b;
while (mod != 0)
{
Expand All @@ -192,6 +193,14 @@ class Fraction <sint64>
}
return b;
}
static sint64 gcds(std::vector<sint64> a)
{
sint64 tem = a.at(0);
for (suint64 i = 1; i < a.size(); i++) {
tem = gcd(tem, a.at(i));
}
return tem;
}
public:
//化简
void Simplification()
Expand Down
174 changes: 172 additions & 2 deletions SeekAnAnswer/SeekAnAnswer/kernel/polynomial.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
#include "polynomial.h"
#include <iostream>
#include <math.h>

//字母因数的迭代器
typedef std::map<sint8, Fraction<sint64>>::iterator FACTOR;

std::set<sint8> S_set_intersection(std::set<sint8> a, std::set<sint8> b)
{
std::set<sint8> intersection;
for (std::set<sint8>::iterator i = a.begin(); i != a.end(); i++)
{
if (b.find(*i) != b.end())
intersection.insert(*i);
}
return intersection;
}

Polynomial::Polynomial(std::string std_value)
{
this->SetValue(std_value);
Expand Down Expand Up @@ -143,21 +155,171 @@ Monomial Polynomial::GetDegree()
return this->list.at(GetLocationOfDegree());
}

Fraction<sint64> Polynomial::GetTheDegree()
{
Fraction<sint64> degree;
Monomial MAX_degree = this->GetDegree();
for (FACTOR it = MAX_degree.GetFactor().begin(); it != MAX_degree.GetFactor().end(); it++)
{
degree += it->second;
}
return degree;
}

suint64 Polynomial::GetLocationOfDegree()
{
Fraction<sint64> degree(0, 1);
suint64 count = 0;
for (suint64 i = 0; i < this->list.size(); i++)
{
if (this->list.at(i).GetDegree() > degree)
if ((this->list.at(i).GetDegree()) > degree)
{
degree = this->list.at(i).GetDegree();
degree = (this->list.at(i)).GetDegree();
count = i;
}
}
return count;
}

Fraction<sint64> Polynomial::GetDegreeOfMixOfchar(sint8 a)
{
//GetTheDegree返回的是该多项式最大的次数,因此不存在某个单项式的字母的次数大于该次数
//所以下面遍历判断比这个小的字母的次数就是最小的
Fraction<sint64> degree = this->GetTheDegree();
for (suint64 i = 0; i < this->list.size(); i++)
{
//如果在这一项单项式中找到该元素
if ((this->list.at(i).GetFactor().find(a)) != (this->list.at(i).GetFactor().end()))
{
if ((this->list.at(i).GetFactor().find(a))->second < degree)
{
degree = (this->list.at(i).GetFactor().find(a))->second;
}
}
}
return degree;
}

Monomial Polynomial::CommonFactor(Polynomial val)
{
Monomial common_factor;

std::vector<sint64> facs;
//取出val的每一项系数
for (suint64 i = 0; i < val.list.size(); i++)
{
facs.push_back(val.list.at(i).GetCoefficient().a);
}
for (suint64 i = 0; i < this->list.size(); i++)
{
facs.push_back(this->list.at(i).GetCoefficient().a);
}
sint64 common_number = Fraction<sint64>::gcds(facs);

common_factor.SetCoefficient(common_number, 1);

std::set<sint8> a_set_intersection;
std::set<sint8> last_set; //上一个单项式的字母集合
std::set<sint8> set; //这个单项式的字母集合
std::set<sint8> set_intersection; //相邻两个单项式的交集

//获取初始的集合,否则下面求交集时结果始终为空集
for (FACTOR j = this->list.at(0).GetFactor().begin(); j != this->list.at(0).GetFactor().end(); j++)
{
set.insert(j->first);
}

//遍历多项式a,获取字母集合
for (suint64 i = 0; i < this->list.size(); i++)
{
//获取单项式的字母集合
for (FACTOR j = this->list.at(i).GetFactor().begin(); j != this->list.at(i).GetFactor().end(); j++)
{
if (i % 2 == 0) last_set.insert(j->first);
else
{
set.insert(j->first);
}
}

if (i % 2 == 1)
{
set_intersection = S_set_intersection(
S_set_intersection(last_set, set),
set_intersection
);

last_set.clear();
}
}
a_set_intersection = set_intersection;

last_set.clear(); set.clear(); set_intersection.clear(); //初始化

//获取初始的集合,否则下面求交集时结果始终为空集
for (FACTOR j = val.list.at(0).GetFactor().begin(); j != val.list.at(0).GetFactor().end(); j++)
{
set.insert(j->first);
}

//遍历多项式a,获取字母集合
for (suint64 i = 0; i < val.list.size(); i++)
{
//获取单项式的字母集合
for (FACTOR j = val.list.at(i).GetFactor().begin(); j != val.list.at(i).GetFactor().end(); j++)
{
if (i % 2 == 0) last_set.insert(j->first);
else
{
set.insert(j->first);
}
}

if (i % 2 == 1)
{
set_intersection = S_set_intersection(
S_set_intersection(last_set, set),
set_intersection
);

last_set.clear();
}
}
//计算两个多项式的字母交集
set_intersection = S_set_intersection(a_set_intersection, set_intersection);

for (std::set<sint8>::iterator it = set_intersection.begin(); it != set_intersection.end(); it++)
{
common_factor.Push(*it, //添加一个字母因数,次数为两个多项式间最小的次数
(this->GetDegreeOfMixOfchar(*it) < val.GetDegreeOfMixOfchar(*it)
? this->GetDegreeOfMixOfchar(*it) : val.GetDegreeOfMixOfchar(*it)));
}

return common_factor;
}

Fraction<sint64> Polynomial::LeastCommonMultiple_of_coe(Polynomial val)
{
std::vector<sint64> a;
for (suint64 i = 0; i < this->list.size(); i++)
{
a.push_back(this->list.at(i).GetCoefficient().b);
}
for (suint64 i = 0; i < val.list.size(); i++)
{
a.push_back(val.list.at(i).GetCoefficient().b);
}

sint64 common_number = Fraction<sint64>::gcds(a);

sint64 temp = 1;
for (suint64 i = 0; i < a.size(); i++)
{
temp *= a.at(i);
}
return Fraction<sint64>(temp / common_number, 1);
}

void Polynomial::Clear()
{
this->list.clear();
Expand Down Expand Up @@ -367,6 +529,14 @@ Polynomial Polynomial::operator/(Polynomial val)
}
}

if (location_of_sonPolynomial == -1)
{
if (result.list.size() == 0)
result.list.push_back(Monomial());

return result;
}

//计算商式
result.list.push_back(remainder.list.at(0) /
val.list.at(location_of_sonPolynomial));
Expand Down
9 changes: 9 additions & 0 deletions SeekAnAnswer/SeekAnAnswer/kernel/polynomial.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,17 @@ class Polynomial
public:
//返回最高次项的单项式
Monomial GetDegree();
//返回最高次项的次数
Fraction<sint64> GetTheDegree();
//返回最高次数的单项式在list表中的下标
suint64 GetLocationOfDegree();
//返回特定字符的最小次数
Fraction<sint64> GetDegreeOfMixOfchar(sint8 a);
public:
//求与val多项式的公因式
Monomial CommonFactor(Polynomial val);
//求与val多项式的最小公倍数
Fraction<sint64> LeastCommonMultiple_of_coe(Polynomial val);
public:
//将最高的单项式的次数的单项式移动到首位
void Move();
Expand Down
Loading

0 comments on commit 458a285

Please sign in to comment.