【问题标题】:Why my random number generator isn't working为什么我的随机数生成器不工作
【发布时间】:2021-02-07 02:07:54
【问题描述】:

检查了输出,种子生成了相同的三个数字,这很烦人。曾经,种子生成器工作正常,然而,它开始做同样的事情,生成相同的三个数字。在 main 和 random_in_unit_sphere() 函数中,随机数生成器每次都打印相同的数字,并且有时会完全跳过循环。 这是随机数种子。

unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    
    std::mt19937 gen(seed);
   
    std::uniform_real_distribution<float> rn1(-1.0, 1.0)

我不知道为什么会这样。

    // Algorithm from http://corysimon.github.io/articles/uniformdistn-on-sphere/
vecfloat random_in_unit_sphere()
{

    vecfloat p(0, 0, 0);
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    // static std::random_device rd;
    std::mt19937 gen(seed);
    ///Random number generator for reflections
    std::uniform_real_distribution<float> rn1(-1.0, 1.0);

    do
    {

        auto x = rn1(gen);
        auto y = rn1(gen);
        auto z = rn1(gen);
        std::cout << "Is it working?" << std::endl;
        p = ((vecfloat((float)x, (float)y, (float)z) * (float)2.0) - vecfloat(1.0f, 1.0f, 1.0f)) * 2.0;

        std::cout << (double)p.squared_length() << std::endl;
    } while ((double)p.squared_length() >= 1.0);
    std::cout << "Is this working?" << std::endl;

    return p;
}
vecfloat color(const ray &r, hittable *world)
{

    hit_record rec;
    //vecfloat unit_direction(0, 0, 0);
    // unit_direction = unit_direction.unit_vector(r.direction());

    // float t = 0.5 * (unit_direction.get_y() + 1.0);
    if (world->hit(r, 0.01, __FLT_MAX__, rec))
    {

        vecfloat target = (rec.p + rec.normal) + random_in_unit_sphere();
        //Recursive function that models real time shadows
        return color(ray(rec.p, target - rec.p), world) * 0.5;
    }
    else
    {

        vecfloat unit_direction(0, 0, 0);
        vecfloat get_unit_direction = unit_direction.unit_vector(r.direction());
        float t = 0.5 * (get_unit_direction.get_y() + 1.0);
        return vecfloat(1.0, 1.0, 1.0) * (float)(1.0 - t) + vecfloat(0.5, 0.7, 1.0) * t;
    }
}

int main()
{

    int nx = 200;
    int ny = 100;
    float ns = 100;

    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::mt19937 gen(seed);
    std::uniform_real_distribution<float> rn1(-1.0, 1.0);

    std::ofstream out("out.ppm");
    raycaster::camera cam;
    out << "P3\n"
        << nx << " " << ny << "\n255\n";

    vecfloat lower_left_corner(-2.0, -1.0, -1.0);
    vecfloat _horizontial(4.0, 0.0, 0.0);
    vecfloat vertical(0.0, 2.0, 0.0);
    vecfloat origin(0.0, 0.0, 0.0);
    hittable *list[2];
    vecfloat a1(0, 0, -1);
    vecfloat a2(0, -100.5, -1);
    list[0] = new sphere(a1, 0.5);
    list[1] = new sphere(a2, 100);
    hittable *world = new hittable_list(list, 2);

    for (int i = ny - 1; i >= 0; i--)
    {
        for (int j = 0; j < nx; j++)
        {
            vecfloat col(0, 0, 0);
            for (int s = 0; s < ns; s++)
            {

                auto x = rn1(gen);
                auto y = rn1(gen);

                float u = float(j + x) / float(nx);
                float v = float(i + y) / float(ny);

                // ray r(origin, (lower_left_corner + ((_horizontial * u) + (vertical * v))));
                ray r = cam.get_ray(u, v);

                vecfloat p = r.point_at_parameter(2.0);
                col += color(r, world);
            }
            col /= float(ns);
            col = col.squared_sides();

            int ir = int(255.99 * col.get_x());
            int ig = int(255.99 * col.get_y());
            int ib = int(255.99 * col.get_z());
            out << ir << " " << ig << " " << ib << "\n";
        }
    }

    return 0;
}

【问题讨论】:

  • 它会生成不同的种子吗?您的种子生成器可能正在计算秒数,并在同一秒内多次生成相同的种子。
  • 不要每次在random_in_unit_sphere中创建std::mt19937,只需在main中创建一次。它的建造成本相对较高,而且你的建造方式每秒只会“改变”一次
  • @SamMason 如果我只在 main 中声明 std:mt19937 我将如何在 randrom_in_unit_sphere 中调用它?
  • 使其全局化或通过引用传递...

标签: c++ random graphics 3d random-seed


【解决方案1】:

看你的代码我太累了,但是如果你想生成一个随机数,那么你应该这样做:

#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
using namespace std;

int main()
{
    // initialize random number generator
    srand(time(0)); // set initial seed value to system clock

    // generate random number
    // ...

    return 0;
}

或者这个:

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
                        // replace the call to rd() with a
                        // constant value to get repeatable
                        // results.

    for (int i = 0; i < 5; ++i)
    {
        cout << gen() << " "; // print the raw output of the generator.
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2017-03-03
    • 2018-11-23
    • 1970-01-01
    • 2013-02-17
    • 2011-05-21
    • 2010-10-30
    相关资源
    最近更新 更多