Filling an array with random numbers from 1 to 10^10 in C or C++

前端 未结 6 1120
你的背包
你的背包 2021-01-27 09:50

a part of an assignment of mine is based on an array (its size is given by the user) which contains random numbers from 1 to 10^10. Then we have to find the k-th smaller number

6条回答
  •  南笙
    南笙 (楼主)
    2021-01-27 10:41

    rand()*rand() isn't going to do anything for you. It doesn't scale the way you think it does, and it does change the distribuon. In fact

    double norm_rand(){
        double r=0;
        for(unsigned i=0;i!=12;++i)
            r+=rand()/static_cast(RAND_MAX);
        return (r/12)-6;
    }
    

    is a common way to simulate a normal distribution with mean 0 and variance 1;

    The best way to to get large random numbers is using a random number device, like /dev/urandom or RtlGenRandom. i.e.

    typedef unsigned long long big_type;
    std::vector rnums;
    std::vector buf(numtoread);
            std::ifstream rnds("/dev/urandom"); 
    rnds.read(reinterpret_cast(&buf[0],buf.size()*sizeof(big_type));
    std::transform(buf.begin(),buf.end(),std::back_inserter(rnums),
         [](big_type const& i){
            return (i*100000000000.)/(std::numeric_limits::max());
         });
    

    At the risk of doing your homework for you, an entirely different approach is to use the libraries that come with C++.

    #include 
    #include 
    #ifndef _MSC_VER  //then assume Linux
    #include 
    #else
    #include 
    #endif
    #include 
    #include 
    #include 
    #include 
    int main(int argc, char** argv)
    {
        assert(argc==3);
        unsigned const numentries=boost::lexical_cast(argv[1]);
        unsigned const k=boost::lexical_cast(argv[2]);
        std::cout<<" finding "< nums(numentries);
        std::tr1::uniform_real<> rng(0.,10000000000.);
        std::tr1::minstd_rand generator(42u);
        std::tr1::variate_generator >
                uni(generator, rng);
        std::generate_n(nums.begin(),nums.size(),uni);
        std::cout<<" Generated:\t ";
        std::copy(nums.begin(),nums.end(),std::ostream_iterator(std::cout,"\t"));
        std::sort(nums.begin(),nums.end());
        std::cout<<"\n The "<

    (If you are in class at the level of just asking for making an array of rand numbers and you hand that in, they'll probably fail you) What I do in practice is to combine the two approaches. This is used in place of the linear conguentual rng used above (the minstd_rand):

    template
    struct randeng {
        typedef bigtype result_type;
        randeng(unsigned x) :
            m_samplesrequired(x), m_samples(x), m_lastused() {
            std::ifstream rand;
            rand.open("/dev/urandom");
            assert(rand);
            rand.read(reinterpret_cast (&*(m_samples.begin())),
                    m_samplesrequired * sizeof(unsigned));
        }
        result_type operator()() const {
            assert(m_lastused::max();
        }
        result_type min() const {
            return 0;
        }
        unsigned m_samplesrequired;
        std::vector m_samples;
        mutable unsigned m_lastused;
    };
    

    This always seems to give much better results.

提交回复
热议问题