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 的调试器工具调试此测试,一切正常,测试通过。谁能描述我为什么这个测试失败了?

4

2 回答 2

0

比你创建新的 Random 实例,它的种子从当前时间初始化,以毫秒为单位。如果一个接一个地创建一个实例,那么种子可能会用一个值初始化。为了防止这种情况,您需要将一个随机实例传递给 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];
            }
        }
    }
于 2012-05-27T00:02:14.577 回答
0

尽管这不是完全重复的,但@LB 的链接回答了这个问题。ARandom使用当前时间戳作为种子进行初始化。如果您使用相同的时间,您将获得相同的“随机”数字。

但是因为您正在创建一个随机数数组,并且该方法还可以执行其他操作,所以它可能会按需要工作。但只是因为它需要更多时间在您当前的机器上执行,所以下一次调用Nextcrates 会生成另一个 double 值列表。

因此,这个软件有可能在一台机器上运行得足够快,以至于总是创建相同的序列。这就是测试失败的原因。

一种解决方案是始终使用相同的实例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();
}
于 2012-05-26T23:45:23.440 回答