1

我正在尝试为一个 uni 项目制作一个随机数生成器。

我正在尝试实现一个函数来获取生成的这个数字列表的周期(数字开始重复之前的时间)。

当我编译并运行它时,它返回 507(这是正确的句点)。

然而,大约 50% 的时间它会返回分段错误。知道发生了什么:

#include<iostream>
#include<fstream>
#include<vector>
#include<math.h>
#include<ctime>

using namespace std;

class Random
{
public:
// Constructor
Random(int a, int b, int m)
{
    this->setMagicNumbers(a,b,m);
}

// Function to set the magic numbers of the random number generator
void setMagicNumbers(int a, int b, int m)
{
    this->A = a;
    this->B = b;
    this->M = m;
}

// Function that returns a list of uniformly distributed random numbers
vector<double> GetUniform(int N, double initialValue = time(0))
{
    double currentNumber = initialValue;
    vector<double> RandomNumbers;
    for(int i = 0; i <= N; i++)
    {
        currentNumber = fmod((this->A*currentNumber) + this->B, this->M);
        RandomNumbers.push_back(currentNumber / this->M); // The number is normalised here
    }
    return RandomNumbers;
}

private:
int A, B, M;
};

class NumberList
{
public:
// Function to add an element to the list
void push(double x)
{
    this->v.push_back(x);
}

// Function to pop an element off the list
double pop()
{
    if(v.size() > 0)
    {
        int popped = v.back();
        v.pop_back();
        return popped;
    }
    else
    {
        cout << "Cannot pop element off empty list." << endl;
        return 0;
    }
    return 0;
}

// Function to get the value at a given location on the list
double getAt(int i)
{
    return this->v[i];
}

    // Function to set the value at a given location on the list
void setAt(int i, double value)
{
    this->v[i] = value;
}

// Function to find the size of the list
unsigned int size()
{
    return this->v.size();
}

// Function to get the vector itself
vector<double> getvector()
{
    return this->v;
}

// Function to set the value of the vector itself
void setVector(vector<double> vec)
{
    this->v = vec;
}

// Function to print the list of numbers as coordinates to a data file
void printCoordinates()
{
        ofstream data("coordinates.dat");
        for(unsigned int i = 0; i <= this->v.size(); i++)
        {
                data << this->v[i] <<  " " << this->v[i + 1] <<  "\n";
        }
        data.close();
}

// Function to print the list of numbers to the terminal
void print()
{
        for(unsigned int i = 0; i <= this->v.size(); i++)
        {
                cout << this->v[i] << endl;
        }
}

// Function to get the period of the list of numbers
int getPeriod()
{
    int i = 2;
    while(true)
    {
        if(isPeriod(i) == true)
        {
            return i;
        }
        else
        {
            i = i + 1;
        }
    }
}

private:
// Vector to hold the values for the list
vector<double> v;

// Function to test if 'i' is the period of the list
bool isPeriod(int i)
{
    for(int j = 0; j != (i-1); j++)
    {
        if(this->getAt(j) != this->getAt(i + j))
        {
            return false;
        }
    }
    return true;
}
};

int main()
{
Random RandNumGenerator(100,104001,714025);                // Create a new random number generator with given magic numbers
NumberList numbers;                                        // Create a blank list of numbers
numbers.setVector(RandNumGenerator.GetUniform(10000));     // Add 10000 random numbers to the list
numbers.printCoordinates();                                // Print out the random numbers as coordinates to a data file
cout << numbers.getPeriod() << endl;                       // Print out the period of the random number list
return 0;
}

提前致谢。

4

3 回答 3

3

此行可能会导致问题

for(unsigned int i = 0; i <= this->v.size(); i++)

有了它,您使用 size 作为最后一个索引,它是溢出的,请尝试为此更改它:

编辑:实际上改变这个

for(unsigned int i = 0; i < this->v.size()-1; i++)

在循环中,您正在访问向量的第 i+1 个元素。

编辑:

这可能不会导致崩溃,但不是创建 N 个元素,而是创建 N+1

for(int i = 0; i <= N; i++)

如果为此更改:

for(int i = 0; i < N; i++)

编辑:修复

#include<iostream>
#include<fstream>
#include<vector>
#include<math.h>
#include<ctime>

using namespace std;

class Random
{
public:
// Constructor
Random(long a, long b, long m)
{
    this->setMagicNumbers(a,b,m);
}

// Function to set the magic numbers of the random number generator
void setMagicNumbers(long a, long b, long m)
{
    this->A = a;
    this->B = b;
    this->M = m;
}

// Function that returns a list of uniformly distributed random numbers
vector<double> GetUniform(int N, double initialValue = time(0))
{
    double currentNumber = initialValue;
    vector<double> RandomNumbers;
    for(int i = 0; i < N; i++)
    {
        currentNumber = fmod((this->A*currentNumber) + this->B, this->M);
        RandomNumbers.push_back(currentNumber / this->M); // The number is normalised here
    }
    return RandomNumbers;
}

private:
long A, B, M;
};

class NumberList
{
public:
// Function to add an element to the list
void push(double x)
{
    this->v.push_back(x);
}

// Function to pop an element off the list
double pop()
{
    if(v.size() > 0)
    {
        int popped = v.back();
        v.pop_back();
        return popped;
    }
    else
    {
        cout << "Cannot pop element off empty list." << endl;
        return 0;
    }
    return 0;
}

// Function to get the value at a given location on the list
double getAt(int i)
{
    return this->v[i];
}

    // Function to set the value at a given location on the list
void setAt(int i, double value)
{
    this->v[i] = value;
}

// Function to find the size of the list
unsigned int size()
{
    return this->v.size();
}

// Function to get the vector itself
vector<double> getvector()
{
    return this->v;
}

// Function to set the value of the vector itself
void setVector(vector<double> vec)
{
    this->v = vec;
}

// Function to print the list of numbers as coordinates to a data file
void printCoordinates()
{
        ofstream data("coordinates.dat");
        for(unsigned int i = 0; i < this->v.size()-1; i++)
        {
                data << this->v[i] <<  " " << this->v[i + 1] <<  "\n";
        }
        data.close();
}

// Function to print the list of numbers to the terminal
void print()
{
        for(unsigned int i = 0; i < this->v.size(); i++)
        {
                cout << this->v[i] << endl;
        }
}

// Function to get the period of the list of numbers
int getPeriod()
{
    int i = 2;
    while(true)
    {
        if(isPeriod(i) == true)
        {
            return i;
        }
        else
        {
            i = i + 1;
        }
    }
}

private:
// Vector to hold the values for the list
vector<double> v;

// Function to test if 'i' is the period of the list
bool isPeriod(int i)
{
    std::cout << "trying period " << i << endl;
    if (i >= v.size()) return true;
    for(int j = 0; j < v.size()-1; j++)
    {
        if(this->getAt(j) == this->getAt(i + j))
        {
            std::cout << "value at j " << this->getAt(j) << "value at i+j " << this->getAt(i+j) <<endl;
            return true;
        }
    }
    return false;
}
};

int main()
{
Random RandNumGenerator(100,104001,714025);                // Create a new random number generator with given magic numbers
NumberList numbers;                                        // Create a blank list of numbers
numbers.setVector(RandNumGenerator.GetUniform(10000));     // Add 10000 random numbers to the list
numbers.printCoordinates();                                // Print out the random numbers as coordinates to a data file
cout << numbers.getPeriod() << endl;                       // Print out the period of the random number list
return 0;
}
于 2012-10-18T23:42:47.737 回答
0

玩了一下这个,我最初认为你的双打向量不知何故被破坏了。我发现如果你将它的大小调整到你想要的确切值——这是一个已知值——段错误就会停止:

vector<double> RandomNumbers(N); // In GetUniform()

运行它gdb是不确定的,因为它看起来好像堆栈被损坏了。我还发现,当我将push_back()just 更改为 0 时:

RandomNumbers.push_back(0.0);

而不是标准化的数字,即使没有向量的初始大小(上图),它也可以正常工作,这表明正在使用的变量之一存在问题。

我还发现,如果我设置currentNumber为 1,而不是调用fmod()- 即使一切都是原来的样子,我也没有出现 seg 错误:

currentNumber = 1;

这种暗示可能与使用fmod()

有趣的是,然后我把电话完全拿出来push_back,发现它仍然有段错误。抱歉,我无法提供更多帮助,但看起来这个地区的某个地方确实发生了某种腐败。

于 2012-10-19T00:41:33.977 回答
0

C++数组的索引中,vector将从 0..size - 1 开始,并且您在整个代码中都滥用了它(inside GetUniform, inside printCoordinates,...),除此之外,在printCoordinates您最后编写的代码this->v[i + 1]中,它将被转换this->v[this->v.size() + 1]为 2 索引之后最后一个有效索引。

但我认为你的错误的来源在getPeriodand isPeriod,看看你从 0 开始到i - 1并检查索引是否匹配 index 的项目i + j,所以如果i变成size() - 1并且大小为 500,那么在更糟糕的情况下,你正在访问v[499 + 498]它比最后一个大有效的索引,您肯定会遇到分段错误。现在要解决它,请检查您的索引并且永远不要超出vector大小的末尾,这意味着您永远不应该使用 index >v.size() - 1

于 2012-10-19T00:58:49.707 回答