2017-10-04 13 views
0

私は、ユーザーからの1つのテキスト入力の機能となるように設計されたプログラムを作成しています。システムクロックの使用、外部ファイルへの参照、マルチスレッドの使用はありません。しかし、プログラムは、私がそれをデバッグするときよりも実行するときに、異なる制御フローで実行されています。実行とデバッグの間の制御フローが異なります

それは自分自身でコンパイルしますが、ここで予想外に動作している機能でありません。

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オブジェクトの値を入力します。このバージョンのgetFactorization()は、簡潔にするために、両方の部分の分母が1であることを前提としています。

sumOfRealAndImaginaryが2に初期化される方法に注意してください。変更されるのは、whileループの一番下で増分されるところです。デバッグモードで、getFactorization()に3 + 4iの値を渡してコードを十分に適度な速度でステップすると、sumOfRealAndImaginary = 3のときに戻ります。これは私が期待するものです。しかし、whileループの先頭にあるWriteLine()コールからわかるように、関数引数として3 + 4iを指定してプログラムを実行すると、sumOfRealAndImaginary = 126まで返されません。特にwhileループ内の最初のif文(コードブロックに関数のreturn文が含まれています)は、デバッグ時よりも実行時にtrueに評価するために、より多くのパスが必要です。予想されるsumOfRealAndImaginary値3だけでなく、それより大きなすべての値についても、真であると評価されるべきです。また、コードを十分に素早く進めて、デバッグモードでを実行すると、そのif文は遅くなるまで評価され続けます。遅くなると、次のパスでtrueに評価されます。したがって、if文が正しく評価されるかどうかは、コードの実行速度によって異なります。何がこの現象を引き起こす可能性がありますか?

私は列挙することができる予期しない動作のより明確なケースがありますが、これで十分です。

編集:PawełŁukasikが要求したComplexNumberクラス。 Fractionは、抽象クラスである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

投稿ComplexNumberクラス –

+2

heisenbugは、競合状態を示唆しているか、デバッガが副作用を持つ式を評価していることを示しています。 *非同期、スレッド、バックグラウンドタスクなどを* *行いますか? – Amy

+0

@Amyもし私がそれらの事柄を持っていれば、私はそれを実現せずに使用することができました。例えば、asyncキーワードを明示的に使用したり、Threadオブジェクトを作成したりするなど、これらのことをプログラムに組み込む微妙な方法はありますか?私が使用した唯一の名前空間は、System、System.Collections.Generic、およびSystem.Textです。 –

答えて

0

他のところでは、Fractionクラスに対して定義したToString()のオーバーロードにreduce()を呼び出す副作用があり、デバッガはToString()を順番に使用するため、何か問題があることが示唆されています変数の値を表示するために、デバッガは私のFractionオブジェクトの内部実行を中断しているかもしれません。これが問題の原因になるのは私には意味がない理由はいくつかありますが、それ以外にも、デバッグを奇妙なものにすることは期待していますが、しかし、私は彼らの提案に留意して、Fractionコンストラクターで起こるすべての削減を手配しました。これが問題を解決しました。これがどのように機能しているかを誰かが明確に説明していれば、それを聞いていただければ幸いです。