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

前端 未结 6 1116
你的背包
你的背包 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:38

    rand()*rand() is a lot different than a single rand(), it decreases the randomness and changes its distribution. See this question for a deeper explanation.

    Also, an integer usually is 4 bytes. It can contain a value as big as 2^31 (2 billions and something) or 2^32 (4 billions and more) if it's unsigned. You can see the max number it can contain checking the INT_MAX macro defined in limits.h. 10^10 is 10 billions, it won't fit in an integer, you'll have to use a bigger type (long long usually is 64 bytes thus more than you need).

    rand, also, returns numbers up to RAND_MAX, and since it returns an int, it won't bigger than INT_MAX. You should use some other way to generate a number as big as 10^10.

    If you don't care about randomness and random number distributions you could sum n random numbers (obtained by rand) so that n=10^10 / RAND_MAX.

    0 讨论(0)
  • 2021-01-27 10:39

    If you take a closer look at 1010 you will notice that it's quite a round limit. My take on this would be to generate each number, one digit at a time and ignoring insignificant zeroes. At this point you would have a number between 0 and 1010-1 inclusive. All you're left with doing is adding a 1.

    As for random()*random(), that is the exact topic of this other question.

    Alin

    0 讨论(0)
  • 2021-01-27 10:39

    Problem #1, an int will only hold a number of size 2^31 in size. You'll need a slightly bigger alternative for your pin array.

    Also, multiplying your two random numbers together really doesn't do much - except perhaps make the number less random.

    Next, you can't create an array on the stack dynamically with the user's input. That will require a new solution to make alloc an array for you.

    0 讨论(0)
  • 2021-01-27 10:39

    you forgot your return statements. at the end of find1 you should be doing:

    if (k==j)
        return arr[j];
    else if (k<j)
        return find1(arr,left,j-1,k);
    else 
        return find1(arr,j+1,right,k-j);
    }
    
    0 讨论(0)
  • 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<double>(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<double> rnums;
    std::vector<big_type> buf(numtoread);
            std::ifstream rnds("/dev/urandom"); 
    rnds.read(reinterpret_cast<char*>(&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<big_type>::max());
         });
    

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

    #include <cassert>
    #include <sstream>
    #ifndef _MSC_VER  //then assume Linux
    #include <tr1/random>
    #else
    #include <random>
    #endif
    #include <boost/lexical_cast.hpp>
    #include <algorithm>
    #include <iterator>
    #include <iostream>
    int main(int argc, char** argv)
    {
        assert(argc==3);
        unsigned const numentries=boost::lexical_cast<unsigned>(argv[1]);
        unsigned const k=boost::lexical_cast<unsigned>(argv[2]);
        std::cout<<" finding "<<k<<"th of "<< numentries<<" entries\n";
        assert(k<=numentries);
        std::vector<double> nums(numentries);
        std::tr1::uniform_real<> rng(0.,10000000000.);
        std::tr1::minstd_rand generator(42u);
        std::tr1::variate_generator<std::tr1::minstd_rand, std::tr1::uniform_real<> >
                uni(generator, rng);
        std::generate_n(nums.begin(),nums.size(),uni);
        std::cout<<" Generated:\t ";
        std::copy(nums.begin(),nums.end(),std::ostream_iterator<double>(std::cout,"\t"));
        std::sort(nums.begin(),nums.end());
        std::cout<<"\n The "<<k<<"th smallest entry is "<<nums[k]<<"\n";
        return 0;
    }
    

    (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<typename bigtype=unsigned>
    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<char*> (&*(m_samples.begin())),
                    m_samplesrequired * sizeof(unsigned));
        }
        result_type operator()() const {
            assert(m_lastused<m_samplesrequired);
            return m_samples[m_lastused++];
        }
        result_type max() const {
            return std::numeric_limits<result_type>::max();
        }
        result_type min() const {
            return 0;
        }
        unsigned m_samplesrequired;
        std::vector<result_type> m_samples;
        mutable unsigned m_lastused;
    };
    

    This always seems to give much better results.

    0 讨论(0)
  • 2021-01-27 10:55
    long long get_big_rand()
    {
    
        long long result;
        do {
            result = (rand() & 0x3ff);
            result <<= 12;
            result |= (rand() & 0xfff);
            result <<= 12;
            result |= (rand() & 0xfff);
        } while (++result > 10000000000ULL);
        return result;
    }
    
    0 讨论(0)
提交回复
热议问题