uniform_real_distribution c++的最小/最大参数出错

Error with min/max arguments of uniform_real_distribution c++

本文关键字:参数 出错 real distribution c++ uniform      更新时间:2023-10-16

我有一个函数可以在正方形晶格上生成一个(伪)随机游动,其中游动不应该突破这个正方形的边界,完整函数如下:

/**
* @brief Performs a single random walk returning the final distance from the origin
*
* Completes a random walk on a square lattice using the mersenne twister engine based pseudo-random
* number-generator (PRNG). The walk will not breach the boundaries of the square size provided to
* the function. The random walk starts at the origin and ends after some parameterised number of steps.
* Position co-ordinates of the walk for each iteration are sent to an output file.
*
* @param squareSideLength Length of square lattice side
* @param steps Number of steps to compute random walk up to
* @param engine Mersenne Twister engine typedef (used for generating random numbers locally)
* @param distribution Default distribution of random walk
* @param outputFile [Default nullptr] Pointer to file to write co-ordinate data of random walk to
* @return final distance of the particle from the origin
*/
double randomWalkSquareLattice(int squareSideLength, int steps, std::mt19937& engine, std::uniform_real_distribution<double>& distribution, std::ofstream* outputFile = nullptr) {
    // store the half-length of the square lattice
    const int halfSquareLength = squareSideLength / 2;
    // initialise co-ordinates to the origin
    double positionX = 0.0;
    double positionY = 0.0;
    // assign the default distribution to distDefault
    std::uniform_real_distribution<double> distDefault = distribution;
    // loop over a number of iterations given by the steps parameter
    for (int i = 0; i < steps; i++) {
        std::cout << positionX << "t" << positionY << std::endl;
        // if the x-position of the particle is >= to positive
        // half square lattice length then generate decremental 
        // random number (avoiding breaching the boundary)
        if (positionX >= halfSquareLength) {
            double offset = positionX - halfSquareLength;
            std::cout << std::endl << offset << std::endl;
            std::uniform_real_distribution<double> distOffset(-offset, -1.0);
            positionX += distOffset(engine);
        }
        // else if the x-position of the particle is <= to negative
        // half square lattice length then generate incremental random
        // number (avoiding breaching the boundary)
        else if (positionX <= -halfSquareLength) {
            double offset = std::abs(positionX + halfSquareLength);
            std::cout << std::endl << offset << std::endl;
            std::uniform_real_distribution<double> distOffset(offset, 1.0);
            positionX += distOffset(engine);
        }
        // else (in case where x-position of particle is not touching 
        // the lattice boundary) generate default random number
        else {
            positionX += distDefault(engine);
        }
        // if the y-position of the particle is >= to positive
        // half square lattice length then generate decremental 
        // random number (avoiding breaching the boundary)
        if (positionY >= halfSquareLength) {
            double offset = positionY - halfSquareLength;
            std::cout << std::endl << offset << std::endl;
            std::uniform_real_distribution<double> distOffset(-offset, -1.0);
            positionY += distOffset(engine);
        }
        // else if the y-position of the particle is <= to negative
        // half square lattice length then generate incremental 
        // random number (avoiding breaching the boundary)
        else if (positionY <= -halfSquareLength) {
            double offset = std::abs(positionY + halfSquareLength);
            std::cout << std::endl << offset << std::endl;
            std::uniform_real_distribution<double> distOffset(offset, 1.0);
            positionY += distOffset(engine);
        }
        // else (in case where y-position of particle is not touching
        // the lattice boundary) generate default random number
        else {
            positionY += distDefault(engine);
        }
        // if an outputFile is supplied to the function, then write data to it
        if (outputFile != nullptr) {
            *outputFile << positionX << "t" << positionY << std::endl;
        }
    }
    // compute final distance of particle from origin
    double endDistance = std::sqrt(positionX*positionX + positionY*positionY);
    return endDistance;
}

方法中看到的条件阻止行走离开边界。然而,当用足够数量的步骤调用它时(以便执行这些条件中的任何一个),我会得到一个错误:

invalid min and max arguments for uniform_real

注意,我发送给这个函数的dist是:

std::uniform_real_distribution<double> dist(-1.0,1.0);

因此(正如您从打印到终端的值中看到的那样)问题并不在于偏移量在任何条件情况下都会大于给定distOffset的最大值。

问题是我不能给u_r_d一个任意精度的双值吗?还是我错过了其他事情?

编辑:我应该补充一下,这些是main()中使用的值:

int main(void) {
    std::uniform_real_distribution<double> dist(-1.0, 1.0);
    std::random_device randDevice;
    std::mt19937 engine(randDevice());
    //std::cout << dist(engine) << std::endl;
    // Dimensions of Square Lattice
    const int squareLength = 100;
    // Number of Steps in Random Walk
    const int nSteps = 10000;
    randomWalkSquareLattice(squareLength, nSteps, engine, dist);
}

uniform_real_distribution(a,b);需要a ≤ b

如果positionX == halfSquareLength,则

double offset = positionX - halfSquareLength;

和说是一样的

double offset = positionX - positionX;

并且CCD_ 4将为零。

这导致

std::uniform_real_distribution<double> distOffset(-0.0, -1.0);

并且违反CCD_ 5。

这是我提出的解决方案,似乎适用于迄今为止的所有测试用例:

/**
* @brief Performs a single random walk returning the final distance from the origin
*
* Completes a random walk on a square lattice using the mersenne twister engine based pseudo-random
* number-generator (PRNG). The walk will not breach the boundaries of the square size provided to
* the function. The random walk starts at the origin and ends after some parameterised number of steps.
* Position co-ordinates of the walk for each iteration are sent to an output file.
*
* @param squareSideLength Length of square lattice side
* @param steps Number of steps to compute random walk up to
* @param engine Mersenne Twister engine typedef (used for generating random numbers locally)
* @param distribution Default distribution of random walk
* @param outputFile [Default nullptr] Pointer to file to write co-ordinate data of random walk to
* @return final distance of the particle from the origin
*/
double randomWalkSquareLattice(int squareSideLength, int steps, std::mt19937& engine, std::uniform_real_distribution<double>& distribution, std::ofstream* outputFile = nullptr) {
// store the half-length of the square lattice
const int halfSquareLength = squareSideLength / 2;
// initialise co-ordinates to the origin
double positionX = 0.0;
double positionY = 0.0;
// assign the default distribution to distDefault
std::uniform_real_distribution<double> distDefault = distribution;
std::uniform_real_distribution<double> distBound(0.0, 1.0);
double oS;
// loop over a number of iterations given by the steps parameter
for (int i = 0; i < steps; i++) {
    //std::cout << positionX << "t" << positionY << std::endl;
    positionX += distDefault(engine);
    positionY += distDefault(engine);
    // if the x-position of the particle is >= to positive
    // half square lattice length then generate decremental 
    // random number (avoiding breaching the boundary)
    if (positionX >= halfSquareLength) {
        oS = distBound(engine);
        double offset = positionX - halfSquareLength;
        double desiredOffset = -(oS + offset);
        if (desiredOffset < -1.0) {
            double offsetFromNegUnity = desiredOffset + 1.0;
            desiredOffset -= offsetFromNegUnity;
        }
        positionX += desiredOffset;
    }
    // else if the x-position of the particle is <= to negative
    // half square lattice length then generate incremental random
    // number (avoiding breaching the boundary)
    else if (positionX <= -halfSquareLength) {
        oS = distBound(engine);
        double offset = std::abs(positionX + halfSquareLength);
        double desiredOffset = offset+oS;
        if (desiredOffset > 1.0) {
            double offsetFromUnity = desiredOffset - 1.0;
            desiredOffset -= offsetFromUnity;
        }
        positionX += desiredOffset;
    }
    // if the y-position of the particle is >= to positive
    // half square lattice length then generate decremental 
    // random number (avoiding breaching the boundary)
    if (positionY >= halfSquareLength) {
        oS = distBound(engine);
        double offset = positionY - halfSquareLength;
        double desiredOffset = -(offset+oS);
        if (desiredOffset < -1.0) {
            double offsetFromNegUnity = desiredOffset + 1.0;
            desiredOffset -= offsetFromNegUnity;
        }
        positionY += desiredOffset;
    }
    // else if the y-position of the particle is <= to negative
    // half square lattice length then generate incremental 
    // random number (avoiding breaching the boundary)
    else if (positionY <= -halfSquareLength) {
        oS = distBound(engine);
        double offset = std::abs(positionY + halfSquareLength);
        double desiredOffset = offset+oS;
        if (desiredOffset > 1.0) {
            double offsetFromUnity = desiredOffset - 1.0;
            desiredOffset -= offsetFromUnity;
        }
        positionY += desiredOffset;
    }
    // if an outputFile is supplied to the function, then write data to it
    if (outputFile != nullptr) {
        *outputFile << positionX << "t" << positionY << std::endl;
    }
}
// compute final distance of particle from origin
double endDistance = std::sqrt(positionX*positionX + positionY*positionY);
return endDistance;
}

这里,在区间(0,1)上随机生成偏移,并将与突破x或y位置的边界的差添加到该偏移中,以创建一个双值,该双值将具有该突破差的最小值和(在附加嵌套条件检查之后)1.0的最大值(或对向边界为-1.0)。