c++ 圆圈中的随机点 - 我哪里出错了?

c++ random point in circle - where did I go wrong?

提问人:MP3D 提问时间:3/1/2023 最后编辑:MP3D 更新时间:3/7/2023 访问量:159

问:

class Solution {
private:
double c_radius;
double xcenter;
double ycenter;

public:
    Solution(double radius, double x_center, double y_center) {
    c_radius = radius;
    xcenter = x_center;
    ycenter = y_center;  
}

vector<double> randPoint() {
    double randomradius= (sqrt((double)rand()) / RAND_MAX) * c_radius;
    double randomangle= ((double)rand() / RAND_MAX) * 360.0;
    double yp= sin(randomangle)*randomradius;
    double xp= cos(randomangle)*randomradius;
    std::vector<double> point= {xp+xcenter, yp+ycenter};
    return point; 
}
};

大家好,我正在做一个关于在圆圈内找到一个随机点的 Leet Code 问题。一切顺利,直到以下测试:输入:[[0.01,-73839.1,-3289891.3]

它本质上是在圆圈内生成一个随机点,但是我的结果似乎是四舍五入的,我不确定为什么。

生成点后的输出:

[null,[-73839.10**000**,-3289891.30**000**],[-73839.10**000**,-3289891.30000],[-73839.10000,-3289891.30000],[-73839.10000,-3289891.30000],[-73839.10000,-3289891.30000]...

预期输出

[null,[-73839.10**006**,-3289891.30**228**],[-73839.10**541**,-3289891.30660],[-73839.10634,-3289891.30124],[-73839.10256,-3289891.30684],[-73839.09825,-3289891.29962]...

现在我的问题是错误在哪里?我的数学有问题吗?结果很接近,但还不够接近。我似乎无法确定此错误发生的位置。任何帮助都非常感谢。

C++ 数学 随机

评论

6赞 Some programmer dude 3/1/2023
你知道三角函数使用弧度作为其角度吗?
0赞 463035818_is_not_an_ai 3/1/2023
它是随机的,为什么期望某些数字?
4赞 Some programmer dude 3/1/2023
顺便问一下,a 代表两个值?似乎有点过分。创建自己的结构(或结构,或类似结构),或使用例如 (或可能)。std::vectorpointvector2std::pair<double, double>std::tuple<double, double>
4赞 chrysante 3/1/2023
此外,对于任何严肃的事情,请考虑使用 C++ 库而不是 C 函数 .<random>rand()
2赞 Adrian Mole 3/1/2023
您应该回滚对问题所做的编辑(即删除答案和修复);否则,它将因“不可重现”而关闭。如果您愿意,可以将评论中给出的“答案”作为实际答案发布。

答:

0赞 Marek R 3/1/2023 #1

使用您目前的方法,您将无法获得均匀分布(即使弧度是固定的)。 点将集中在一个中心。

任务描述说点分布应该是均匀的,但我怀疑是否编写了适当的统计测试。

相反,使这变得复杂,只需在包含圆的正方形中随机选择坐标,然后继续生成该点,直到它适合圆。

class Solution {
    std::mt19937 gen;
    std::uniform_real_distribution<> dis;
    double xc;
    double yc;
    double r2;

public:
    Solution(double radius, double x_center, double y_center) 
        : dis{-radius, radius}
        , xc{x_center}
        , yc{y_center}
        , r2{radius * radius}
    {
    }
    
    std::vector<double> randPoint() {
        double dx, dy;
        do {
            dx = dis(gen);
            dy = dis(gen);
        } while (dx*dx + dy*dy > r2);
        return {xc + dx, yc + dy};
    }
};

评论

0赞 MP3D 3/1/2023
考虑到该函数最多会被调用 3 * 10^4 次,这不是非常低效吗?
0赞 Marek R 3/1/2023
恰恰相反。与圆形相比,被拒绝的区域非常小。这个区域的78%是一个圆。 并且比重试慢得多,检查点在一个圆圈内。sincossqrt
0赞 MP3D 3/1/2023
很酷,学到了一些东西!但是,我真的不确定 std::mt19937 gen;std::uniform_real_distribution<> 以及如何使用它们。谢谢你的回答。
0赞 Marek R 3/1/2023
用性能来证明这一点:quick-bench.com/q/4YLsNRGjt5kd-IfRtizk99Cf0u4
0赞 MP3D 3/1/2023 #2

似乎我在错误的地方进行了手术。使用后我计算了通过测试的结果。(感谢 chrysante) 完整代码:sqrt()sqrt()rand()/RAND_MAX

class Solution {
private:
double c_radius;
double xcenter;
double ycenter;

public:
Solution(double radius, double x_center, double y_center) {
    c_radius = radius;
    xcenter = x_center;
    ycenter = y_center;  
}

vector<double> randPoint() {
    double randomradius= sqrt(((double)rand() / RAND_MAX)) * c_radius;
    double randomangle= ((double)rand() / RAND_MAX) * 360.0;
    double yp= sin(randomangle)*randomradius;
    double xp= cos(randomangle)*randomradius;
    return {xp+xcenter, yp+ycenter};
}
};

此代码通过了所有 Leetcode 测试。平方生根的结果是必要的,否则会抛出与原始帖子相同的错误。rand()/RAND_MAX

评论

0赞 Marek R 3/1/2023
您已经复制了 360 错误,请参阅“问题”下的评论。