我正在编写一个程序,其行为我设计为来自用户的单个文本输入的功能而没有别的。没有使用系统时钟,没有引用外部文件,没有多线程。但是,当我运行它时,程序执行的控制流程与我调试时的控制流程不同,我认为在这种情况下应该是不可能的。
它不会自行编译,但这是一个意外行为的函数:
static public Dictionary<ComplexNumber, int> getFactorization(ComplexNumber xGaussian)
{
Dictionary<ComplexNumber, int> factors = new Dictionary<ComplexNumber, int>();
int sumOfRealAndImaginary = 2;
while (true)
{
Console.WriteLine(sumOfRealAndImaginary);//test
int realPart = sumOfRealAndImaginary / 2;
int imaginaryPart = sumOfRealAndImaginary - realPart;
for (int i = 0; realPart - i >= 0;)
{
if ((realPart - i) * (realPart - i) +
(imaginaryPart + i) * (imaginaryPart + i) >
xGaussian.getRealPart().getNumerator() *
xGaussian.getRealPart().getNumerator() +
xGaussian.getImaginaryPart().getNumerator() *
xGaussian.getImaginaryPart().getNumerator())
{
if (factors.ContainsKey(xGaussian))
factors[xGaussian] += 1;
else
factors.Add(xGaussian, 1);
return factors;
}
ComplexNumber factor =
new ComplexNumber(realPart - i, imaginaryPart + i);
ComplexNumber quotient = (ComplexNumber)(xGaussian / factor);
quotient.getRealPart().reduce();
quotient.getImaginaryPart().reduce();
if (quotient.getRealPart().getDenominator() == 1 &&
quotient.getImaginaryPart().getDenominator() == 1)
{
if (factors.ContainsKey(factor))
factors[factor] += 1;
else
factors.Add(factor, 1);
xGaussian = (ComplexNumber)(xGaussian / factor);
continue;
}
factor = new ComplexNumber(realPart - i, -imaginaryPart - i);
quotient = (ComplexNumber)(xGaussian / factor);
quotient.getRealPart().reduce();
quotient.getImaginaryPart().reduce();
if (quotient.getRealPart().getDenominator() == 1 &&
quotient.getImaginaryPart().getDenominator() == 1)
{
if (factors.ContainsKey(factor))
factors[factor] += 1;
else
factors.Add(factor, 1);
xGaussian = (ComplexNumber)(xGaussian / factor);
continue;
}
++i;
}
++sumOfRealAndImaginary;
}
}
ComplexNumber类型的设计方式与复数在数学中的行为相同,但仅限于有理的实部和虚部,因此我将以与复数中的复数相同的方式键入ComplexNumber对象的值。数学。这个版本的getFactorization()假设两个部分的分母都是1,为简单起见。
注意sumOfRealAndImaginary如何初始化为2,并且它唯一被改变的地方是它在while循环的底部递增的位置。在调试模式下,当我传递getFactorization()值3 + 4i并以足够中等的速度逐步执行代码时,它会在sumOfRealAndImaginary = 3时返回。这就是我所期望的。但是,当我运行程序时,也使用3 + 4i作为函数参数,直到sumOfRealAndImaginary = 126才会返回,这可以从while循环顶部的WriteLine()调用中看出。特别是,while循环中的第一个if语句,其代码块包含函数的return语句,在运行时需要更多的传递来评估为true,而不是在调试时。它不仅应该对期望的sumOfRealAndImaginary值为3,而且对于大于该值的每个值都要求为true。此外,当我在调试模式下快速单步执行代码 时,if语句将继续评估为false,直到我减速为止,此时它会在下一次传递时计算为true。因此,似乎if语句是否正确评估取决于代码的执行速度。什么可能导致这种行为?
我可以枚举更多不同的意外行为案例,但也许这足以启动。
编辑:根据PawełŁukasik的要求,ComplexNumber类。分数是一个类似的类,也是从Number类派生的,它是抽象的。
public class ComplexNumber : Number
{
Fraction m_real;
Fraction m_imaginary;
public ComplexNumber(Fraction real, Fraction imaginary)
{
m_real = real;
m_imaginary = imaginary;
}
public ComplexNumber(int real, int imaginary)
{
m_real = new Fraction(real, 1);
m_imaginary = new Fraction(imaginary, 1);
}
public Fraction getRealPart()
{
return m_real;
}
public Fraction getImaginaryPart()
{
return m_imaginary;
}
protected override Number add(Number number)
{
if (number is Fraction)
{
Fraction fraction = (Fraction)number;
return new ComplexNumber((Fraction)(m_real + fraction), m_imaginary);
}
ComplexNumber complexNumber = (ComplexNumber)number;
return new ComplexNumber((Fraction)(m_real + complexNumber.m_real),
(Fraction)(m_imaginary + complexNumber.m_imaginary));
}
protected override Number subtract(Number number)
{
if (number is Fraction)
{
Fraction fraction = (Fraction)number;
return new ComplexNumber((Fraction)(m_real - fraction), m_imaginary);
}
ComplexNumber complexNumber = (ComplexNumber)number;
return new ComplexNumber((Fraction)(m_real - complexNumber.m_real),
(Fraction)(m_imaginary - complexNumber.m_imaginary));
}
protected override Number multiply(Number number)
{
if (number is Fraction)
{
Fraction fraction = (Fraction)number;
return new ComplexNumber((Fraction)(m_real * fraction),
(Fraction)(m_imaginary * fraction));
}
ComplexNumber complexNumber = (ComplexNumber)number;
return new ComplexNumber((Fraction)(m_real * complexNumber.m_real - m_imaginary *
complexNumber.m_imaginary), (Fraction)(m_real * complexNumber.m_imaginary +
m_imaginary * complexNumber.m_real));
}
protected override Number multiply(int scalar)
{
return new ComplexNumber((Fraction)(m_real * scalar),
(Fraction)(m_imaginary * scalar));
}
protected override Number divide(Number number)
{
if (number is Fraction)
{
Fraction fraction = (Fraction)number;
return new ComplexNumber((Fraction)(m_real / fraction),
(Fraction)(m_imaginary / fraction));
}
ComplexNumber complexNumber = (ComplexNumber)number;
return new ComplexNumber((Fraction)((Fraction)(m_real * complexNumber.m_real +
m_imaginary * complexNumber.m_imaginary) / (Fraction)(complexNumber.m_real *
complexNumber.m_real + complexNumber.m_imaginary * complexNumber.m_imaginary)),
(Fraction)((Fraction)(m_imaginary * complexNumber.m_real -
m_real * complexNumber.m_imaginary) / (Fraction)(complexNumber.m_real
* complexNumber.m_real + complexNumber.m_imaginary * complexNumber.m_imaginary)));
}
public override string ToString()
{
StringBuilder output = new StringBuilder();
if (m_imaginary.getNumerator() != 0)
{
m_imaginary.reduce();
if (m_imaginary.getNumerator() > 0)
{
if (m_real.getNumerator() != 0)
{
output.Append(m_real.ToString());
output.Append("+");
}
if (m_imaginary.getNumerator() != 1)
output.Append(m_imaginary.getNumerator());
}
else if (m_imaginary.getNumerator() < 0)
{
if (m_real.getNumerator() != 0)
output.Append(m_real.ToString());
output.Append("-");
if (m_imaginary.getNumerator() != -1)
output.Append(-m_imaginary.getNumerator());
}
output.Append("i");
if (m_imaginary.getDenominator()!=1)
{
output.Append("/");
output.Append(m_imaginary.getDenominator());
}
}
else if (m_real.getNumerator() != 0)
output.Append(m_real.ToString());
else
return "0";
return output.ToString();
}
public override bool Equals(object obj)
{
if (obj is ComplexNumber)
{
ComplexNumber complexNumber = (ComplexNumber)obj;
return m_real.Equals(complexNumber.m_real) &&
m_imaginary.Equals(complexNumber.m_imaginary);
}
return false;
}
public override int GetHashCode()
{
return m_real.GetHashCode() | m_imaginary.GetHashCode();
}
}
再次编辑:a link to a text file of the whole program,就此而言。
答案 0 :(得分:0)
其他人建议问题与我为Fraction类定义的ToString()的重载具有调用reduce()的副作用这一事实有关,并且因为调试器使用ToString()以便显示变量的值,调试器可能一直在搞乱我的Fraction对象执行中的内部。有几个原因导致我觉得这不是问题的原因,其中最重要的是我希望它能使调试行为异常,但让运行不受影响而不是另一种方式,但我听从他们的建议,并安排在Fraction构造函数中发生所有减少,这确实解决了问题。如果有人对这是如何工作有更明确的解释,我将不胜感激。