我在使用 Windows 窗体创建多项式计算器时遇到了问题。我有两个用于两个多项式和四个按钮的文本框,
+
,-
,*
,/
.
示例多项式:
"-x^10-2x^4+3x^2-2x-2",
"0",
"-10x^5-1",
"-x"
我引用了每个按钮并从文本框中获取数据。每次我尝试将多项式解析为数组时,我都会出错或者我没有得到正确的值。
谁知道如何编写这样的parsing和reverse函数,即从数组到多项式字符串? 或者有人知道一个易于用于此类操作的库吗?
将多项式字符串解析为数组可以通过将字符串拆分为单独的项然后分别解析每个项来实现。这是一个示例代码片段,展示了如何执行此操作:
string input = "-x^10-2x^4+3x^2-2x-2";
string[] terms = input.Split('+', '-');
List<int> coefficients = new List<int>();
List<int> exponents = new List<int>();
foreach (string term in terms)
{
if (term == "")
{
continue;
}
int coefficient = 1;
int exponent = 0;
if (term.Contains("x"))
{
if (term.Contains("^"))
{
string[] parts = term.Split('^');
exponent = int.Parse(parts[1]);
}
else
{
exponent = 1;
}
if (term.Contains("-x"))
{
coefficient = -1;
}
else if (term.Contains("x"))
{
string[] parts = term.Split('x');
if (parts[0] == "-")
{
coefficient = -1;
}
else if (parts[0] != "")
{
coefficient = int.Parse(parts[0]);
}
}
}
else
{
coefficient = int.Parse(term);
}
coefficients.Add(coefficient);
exponents.Add(exponent);
}
int[] coefficientsArray = coefficients.ToArray();
int[] exponentsArray = exponents.ToArray();
此代码使用 Split 方法将输入字符串拆分为单独的术语。然后循环遍历每个项并使用各种字符串操作提取系数和指数。提取的值被添加到单独的列表中,然后使用 ToArray 方法将其转换为数组。
要将数组转换回多项式字符串,您可以遍历每个项并使用字符串连接手动构造字符串。这是一个示例代码片段,展示了如何执行此操作:
int[] coefficientsArray = new int[] { -1, -2, 3, -2, -2 };
int[] exponentsArray = new int[] { 10, 4, 2, 1, 0 };
StringBuilder output = new StringBuilder();
for (int i = 0; i < coefficientsArray.Length; i++)
{
int coefficient = coefficientsArray[i];
int exponent = exponentsArray[i];
if (coefficient == 0)
{
continue;
}
if (coefficient > 0 && i > 0)
{
output.Append("+");
}
if (coefficient == -1 && exponent > 0)
{
output.Append("-");
}
else if (coefficient != 1 || exponent == 0)
{
output.Append(coefficient);
}
if (exponent > 0)
{
output.Append("x");
if (exponent > 1)
{
output.Append("^");
output.Append(exponent);
}
}
}
string outputString = output.ToString();
此代码遍历每个术语并使用字符串连接手动构造字符串。 StringBuilder 类用于在构造字符串时提高性能。该代码处理各种特殊情况,例如跳过系数为 0 的项,正确处理第一项,以及在 1x 或 x^1 等特殊情况下省略系数和指数。
我建议使用正则表达式:我们匹配像
-1265 * x ^ 5
这样的词,然后我们分析:
using System.Linq;
using System.Text.RegularExpressions;
...
private static IEnumerable<(double factor, int power)> ParsePolynom(string source) {
return Regex
.Split(source, @"(?<![eE]\s*)(?<!^\s*)[+-]")
.Select(item => item.Split('x'))
.Select(items => {
string factorString = items[0].TrimEnd(' ', '*').Replace(" ", "");
double factor =
string.IsNullOrEmpty(factorString) ? 1.0
: factorString == "-" ? -1.0
: double.Parse(factorString);
if (items.Length == 1)
return (factor, power: 0);
string power = items[1].Trim(' ', '^');
if (string.IsNullOrEmpty(power))
return (factor, power: 1);
return (factor, power: int.Parse(power));
})
.OrderByDescending(item => item.power);
}
演示:
string[] tests = {
"-123 + 14.5e3 * x - 12.6e-5 * x ^ 4",
"1e23",
"x",
"x + x ^ 2",
"-x - 2.36 x^2",
"-x^10-2x^4+3x^2-2x-2",
"0",
"-10x^5-1",
"-x"
};
string report = string.Join(Environment.NewLine, tests
.Select(test => string.Join(" ", ParsePolynom(test))));
Console.Write(report);
输出:
(0.000126, 4) (14500, 1) (-123, 0)
(1E+23, 0)
(1, 1)
(1, 2) (1, 1)
(2.36, 2) (-1, 1)
(-1, 10) (2, 4) (3, 2) (2, 1) (2, 0)
(0, 0)
(-10, 5) (1, 0)
(-1, 1)
反向很简单:我们将每个项目变成字符串,然后将它们连接起来:
private static string PolynomToString(IEnumerable<(double factor, int power)> source) {
return string.Concat(source
.Select(item => $"{(item.factor > 0 ? "+" : "")}{item.factor}x^{item.power}"));
}
使用 Regex
@"([-+]?)([0-9]*)(x?)(\^?)([0-9]*)"
和 Match 完成这项工作
string input = "-x^10-2x^4+3x^2-2x-2";
var dico = new Dictionary<int, int>();// (expo, coef)
_ = Regex.Replace(input, @"([-+]?)([0-9]*)(x?)(\^?)([0-9]*)",
m =>
{
if (string.IsNullOrEmpty(m.Value)) return "";
var sign = m.Groups[1].Value == "-" ? -1 : 1;
var coef = int.Parse(m.Groups[2].Value == "" ? "1" : m.Groups[2].Value) * sign;
var xxxx = m.Groups[3].Value;
if(xxxx == "")
{
dico[0] = coef;
return "";
}
var expo = int.Parse(m.Groups[4].Value == "" ? "1" : m.Groups[5].Value);
dico[expo] = coef;
return "";
});
foreach (var (k, v) in dico.OrderByDescending(x => x.Key))
System.Diagnostics.Debug.WriteLine($"coef: {v} expo: {k}");
结果在迪科
coef: -1 expo: 10
coef: -2 expo: 4
coef: 3 expo: 2
coef: -2 expo: 1
coef: -2 expo: 0