使用C或C ++中的1到10 ^ 10的随机数填充数组

时间:2011-01-15 17:05:17

标签: c++ c arrays random

我的任务的一部分基于数组(其大小由用户给出),其包含从1到10 ^ 10的随机数。然后我们必须找到第k个较小的数组。这是我试过的:

#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <time.h>

using namespace std;

void swap(int *x,int *y)
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

int choose_pivot(int i,int j )
{
    return((i+j) /2);
}

// Print array
void printarr(int arr[],int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%d\t",arr[i]);
}

// Find algorithm
int find1(int arr[],int left,int right,int k)
{
    int i,j,pivot;
    if (left==right)
        return arr[left];
    else
    {
        i=left;
        j=right+1;
        pivot= arr[left];
        do
        {
            do {
                i=i+1;
            } while (arr[i]>=pivot);
            do {
                j =j-1;
            } while (arr[j]<=pivot);
            if (i<j)
                swap(arr[i],arr[j]);
        } while (j<=i);
    }
    swap(arr[left],arr[j]);
    if (k==j)
        return arr[j];
    else if (k<j)
        find1(arr,left,j-1,k);
    else 
        find1(arr,j+1,right,k-j);
}

int main(int argc, char *argv[])
{
    srand(time(NULL));
    int n,i,fi,k;
    printf("Give array's size:\n");
    scanf("%d",&n);
    int pin[n];
    for (i=0;i<n;i++)
        pin[i]=((rand()*rand()) % 1000000000) +1;
    printf("Give k: \n");
    scanf("%d",&k);
    printf("The array contains the following numbers:\n\n");
    printarr(pin,n);
    fi=find1(pin,0,n-1,k);//find the k-th smallest number in the array
    printf("The k-th smallest number is: %d",fi);

    system("PAUSE");
}

正如你所看到的,10 ^ 10是一个非常大的值,我用其他数字填充数组。这是对的吗?我还能做些什么吗? 我的第二个问题是查找算法。它不起作用。有人可以帮我这些吗?非常感谢你

6 个答案:

答案 0 :(得分:3)

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;
}

答案 1 :(得分:2)

rand()*rand()与单个rand()有很大不同,它会降低随机性并更改其分布。有关更深入的解释,请参阅this question

此外,整数通常为4个字节。如果它是未签名的,它可以包含一个大到2^31(20亿美元)或2^32(40亿甚至更多)的值。您可以查看INT_MAX中定义的limits.h宏可以包含的最大数量。 10^10是10亿,它不适合整数,你必须使用更大的类型(long long通常是64字节,因此比你需要的多。)

rand也会返回最多RAND_MAX的数字,因为它返回int,所以它不会大于INT_MAX。您应该使用其他方式生成与10^10一样大的数字。

如果您不关心随机数和随机数分布,您可以将n个随机数(由rand获得)加总,以便n=10^10 / RAND_MAX

答案 2 :(得分:2)

如果仔细观察10 10 ,你会发现它是一个非常圆的限制。我对此的看法是生成每个数字,一次一个数字,忽略无关紧要的零。此时,您将有一个0到10之间的数字 10 -1(含)。你剩下的就是添加1。

至于random()*random(),这是this other question完全主题。

阿林

答案 3 :(得分:2)

问题#1,int只能容纳2 ^ 31大小的数字。您的引脚阵列需要稍大的替代方案。

此外,将两个随机数相加在一起确实没有太大作用 - 除非使数字更少随机。

接下来,您无法使用用户的输入动态地在堆栈上创建数组。这需要一个新的解决方案来为你分配一个数组。

答案 4 :(得分:1)

rand()* rand()不会为你做任何事情。它不会像你想象的那样扩展,它确实改变了分布。事实上

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

是模拟具有均值0和方差1的正态分布的常用方法;

获取大型随机数的最佳方法是使用随机数设备,如/ dev / urandom或RtlGenRandom。 即。

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());
     });

冒着为你做功课的风险,一种完全不同的方法是使用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;
}

(如果你在课堂上只是要求制作一系列兰特数字并将其交给他们,他们可能会让你失望) 我在实践中做的是结合这两种方法。这用于代替上面使用的线性conguentual rng(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;
};

这似乎总能给出更好的结果。

答案 5 :(得分:0)

你忘了你的回复陈述了。在find1结束时你应该这样做:

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);
}