2012-05-26 2 views
0

나는이 클래스의 선형 방정식이상한 행동은

public class MatrixGenerator: IMatrixGenerator 
    { 
     private int vSize; 
     private int hSize; 
     private double[,] _matrix; 
     private double[] _right; 
     private double[] _solution; 
     private double maxValue; 

     public MatrixGenerator(int vSize, int hSize, double maxValue) 
     { 
      this.vSize = vSize; 
      this.hSize = hSize; 
      this.maxValue = maxValue; 
      _matrix = new double[vSize, hSize]; 
      _right = new double[vSize]; 
      _solution = new double[hSize]; 
     } 

     public void Next() 
     { 
      _matrix = new double[vSize, hSize]; 
      _right = new double[vSize]; 
      Random r = new Random(); 
      _solution = Enumerable.Repeat(0.0, hSize).Select(m => m = r.NextDouble()*maxValue).ToArray(); 

      for (int i = 0; i < vSize; i++) 
      { 
       for (int j = 0; j < hSize; j++) 
       { 
        _matrix[i, j] = r.NextDouble() * maxValue; 
       } 
       for (int j = 0; j < hSize; j++) 
       { 

        _right[i] += _solution[j] * _matrix[i, j]; 
       } 
      } 
     } 

     public double[,] Matrix 
     { 
      get { return _matrix; } 
     } 

     public double[] RightVector 
     { 
      get { return _right; } 
     } 

     public double[] SolutionVector 
     { 
      get { return _solution; } 
     } 
    } 

와 NUnit과 테스트의 임의의 시스템을 생성 클래스가 있습니다

[Test] 
     public void CanGenerateAnotherMatrixandVector() 
     { 
      MatrixGenerator mGen = new MatrixGenerator(vSize, hSize, maxValue); 
      mGen.Next(); 
      double[,] firstMatrix = new double[mGen.Matrix.GetLength(0), mGen.Matrix.GetLength(1)]; 
      double[] firstVector = new double[mGen.RightVector.GetLength(0)]; 
      for (int i = 0; i < mGen.Matrix.GetLength(0); i++) 
      { 
       firstVector[i] = mGen.RightVector[i]; 
       for (int j = 0; j < mGen.Matrix.GetLength(1); j++) 
       { 
        firstMatrix[i,j] = mGen.Matrix[i, j]; 
       } 
      } 
      mGen.Next(); 

      Assert.That(firstMatrix, Is.Not.EqualTo(mGen.Matrix)); 
      Assert.That(firstVector, Is.Not.EqualTo(mGen.RightVector)); 
     } 

테스트 실패를하지만,이 코드는 작품입니다. TestDriven.Net에서 디버거 도구로이 테스트를 디버그 해보고 모든 것이 작동하고 테스트가 통과되었습니다. 아무도 왜이 테스트가 실패하는지 설명 할 수 있습니까?

+2

당신은 아마 그것의 경우 각 시간이 그럴듯 같은 임의의 숫자가 발생할 수 있습니다 인스턴스로'Random' 개체의 인스턴스를 재사용한다 충분히 빠른 처리. –

+0

@ChrisSinclair에 따르면'Random r = new Random(); '을 호출하면 충분히 빨리 동일한 시퀀스를 얻을 수 있습니다. 'r'을 한 번만 만듭니다. http://stackoverflow.com/questions/767999/random-number-generator-not-working-the-way-i-had-planned-c –

+0

마지막으로 전화하기 전에 지연을 사용하면 적절하다고 생각합니다. 다음() 메서드는이 테스트를 통과하면 – HaMI

답변

0

정확하게 일치하지는 않지만 @ L.B의 링크가이 질문에 대답합니다. Random은 시드로 현재 타임 스탬프로 초기화됩니다. 같은 시간을 사용하면 동일한 '임의의'번호가 표시됩니다.

하지만 임의의 숫자 배열을 만들고이 메서드는 다른 것들도 수행하기 때문에 원하는대로 작동 할 수 있습니다. 그러나 현재 컴퓨터에서 실행하는 데 더 많은 시간이 필요하기 때문에 Next의 다음 호출은 이중 값의 다른 목록을 만듭니다.

따라서이 소프트웨어는 항상 동일한 시퀀스를 항상 충분히 빠르게 실행할 수있는 컴퓨터에서 실행될 수 있습니다. 그것이 시험이 실패하는 이유입니다.

해결 방법은 로컬 변수 대신 멤버 변수를 사용하는 등 항상 동일한 인스턴스 인 Random을 사용하는 것입니다. 이 경우

public class MatrixGenerator: IMatrixGenerator 
{ 
    // ... 
    Random r = new Random(); 

    // ... 

    public void Next() 
    { 
     _matrix = new double[vSize, hSize]; 
     _right = new double[vSize]; 
     _solution = Enumerable.Repeat(new Random(), hSize) 
           .Select(r => r.NextDouble() * maxValue) 
           .ToArray(); 
     // ... 

MatrixGenerator의 생성자 또는 Next 메소드에 인수로서 임의의 인스턴스를 전달하기에도 좋습니다.

var random = new Random(); 
for(int i = 0; i< 1000; i++) 
{ 
    var mGen = new MatrixGenerator(4, 5, 10, random); 
    mGen.Next(); 
} 
0

새 임의 인스턴스를 만들 때보다 seed initialised form the current time 밀리 초 단위로 만듭니다. 다른 인스턴스 바로 뒤에서 하나의 인스턴스를 만드는 경우 시드는 하나의 값으로 초기화 될 수 있습니다. 이를 방지하기 위해 임의의 인스턴스 하나를 Next 메서드로 전달해야합니다.

테스트 :

 var random = new Random(); 
     var mGen = new MatrixGenerator(4, 5, 10); 
     mGen.Next(random); 

     var firstMatrix = new double[mGen.Matrix.GetLength(0),mGen.Matrix.GetLength(1)]; 
     var firstVector = new double[mGen.RightVector.GetLength(0)]; 

     for (int i = 0; i < mGen.Matrix.GetLength(0); i++) { 
      firstVector[i] = mGen.RightVector[i]; 
      for (int j = 0; j < mGen.Matrix.GetLength(1); j++) { 
       firstMatrix[i, j] = mGen.Matrix[i, j]; 
      } 
     } 
     mGen.Next(random); 

     CollectionAssert.AreNotEqual(firstMatrix, mGen.Matrix); 
     CollectionAssert.AreNotEqual(firstVector, mGen.RightVector); 

새로운 다음 방법

public void Next(Random random) { 
     _matrix = new double[vSize,hSize]; 
     _right = new double[vSize]; 

     _solution = Enumerable.Repeat(0.0, hSize).Select(m => random.NextDouble()*maxValue).ToArray(); 

     for (int i = 0; i < vSize; i++) { 
      for (int j = 0; j < hSize; j++) { 
       _matrix[i, j] = random.NextDouble()*maxValue; 
      } 
      for (int j = 0; j < hSize; j++) { 
       _right[i] += _solution[j]*_matrix[i, j]; 
      } 
     } 
    } 
+0

고맙습니다. – HaMI