免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1516 | 回复: 4
打印 上一主题 下一主题

[算法] 求随机数字算法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-10-16 14:48 |只看该作者 |倒序浏览
{202.205.0.0/28;205.12.0.0/26};
这是关于求随机数的问题。
首先这是一段网络段,现在可以将他解析出来202.205.0.0就是IP地址后面的28其实就是32-28=4,2的4次方=16,那么这段IP地址就是202.205.0.0-202.205.0.16.
所以{202.205.0.0/28;205.12.0.0/26}中应该是有16+64=80个IP地址。
现在要在这80个IP地址中随机取20个IP。(我只是举个列子,之前用容器做的,我把所有IP都放到容器中内存不足了,其实正常数据一个段里有上万个IP,有上万个段,所以有几亿数据)
16,64是我都能知道的,我还能知道就是首IP地址,比如202.205.0.0和205.12.0.0。
现在想获得一个随机数,比如72,72在80以内,其实它的地址应该是72-16=56,那应该就是205.12.0.0+52也就是205.12.0.52,这样想我能想明白
while(iplist!=it->second.end())
{
        unsigned long int ip_num=imask-iplist->mask;

        for(unsigned long int i=iplist->net_id+firstend;i<iplist->net_id+everyip_num-firstend;i++)
        {
                v.push_back(i);
        }
        iplist++;
        everyip_num+=ip_num;       
}
上述代码中while循环就是循环{202.205.0.0/28;205.12.0.0/26}2组数据,ip_num=imask-iplist->mask;就是每组的IP数,16和64,everyip_num就是总IP数80;
for(unsigned long int i=iplist->net_id;i<iplist->net_id+everyip_num;i++)
        {
                v.push_back(i);
        }
按照这种插入数据的办法肯定有问题,数据过多会把容器爆掉,现在就随机插入20个,其中iplist->net_id就是IP地址,之前是循环一组就把IP都放到容器里,现在是要随机放20个,如果随机数是76的话,代码要怎么写?





论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
2 [报告]
发表于 2015-10-16 17:52 |只看该作者
楼主,我看不懂你的 语文描述。。。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
3 [报告]
发表于 2015-10-16 17:54 |只看该作者
应该是有16+64=80个IP地址。

这个64是哪里来的。。。再描述详细点吧。。

先不管其他的,看上去随机应该是某个范围内,或者是几个范围内的,何必使用容器。。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
4 [报告]
发表于 2015-10-17 01:00 |只看该作者
本帖最后由 windoze 于 2015-10-17 01:54 编辑

嗯,lz的这个问题我还真的想了想,发现还是需要写点代码的

https://gist.github.com/windoze/ ... #file-gistfile1-txt

  1. #include <cstdint>
  2. #include <array>
  3. #include <vector>
  4. #include <iostream>
  5. #include <random>

  6. inline constexpr uint32_t subnet_mask(int len) {
  7.     return 0xFFFFFFFF >> (32-len) << (32-len);
  8. }

  9. inline uint8_t read_segment(const std::string &s, size_t start_pos) {
  10.     return 0;
  11. }

  12. struct IP_addr {
  13.     uint32_t data;
  14.    
  15.     // NOTE: Hardcoded little endian u32
  16.     uint8_t &operator[](size_t index)
  17.     { return reinterpret_cast<uint8_t *>(&data)[3-index]; }
  18.    
  19.     // NOTE: Hardcoded little endian u32
  20.     const uint8_t &operator[](size_t index) const
  21.     { return reinterpret_cast<const uint8_t *>(&data)[3-index]; }
  22.    
  23.     IP_addr mask(int len) const { return IP_addr{data & subnet_mask(len)}; }
  24.     template<typename Iterator>
  25.     static IP_addr parse(Iterator begin, Iterator end) {
  26.         IP_addr ret{0};
  27.         size_t index = 0;
  28.         while (begin!=end) {
  29.             if (isdigit((unsigned char)*begin)) {
  30.                 ret[index] *= 10;
  31.                 ret[index] += *begin - '0';
  32.             } else {
  33.                 ++index;
  34.             }
  35.             ++begin;
  36.         }
  37.         return ret;
  38.     }
  39. };

  40. inline std::ostream &operator << (std::ostream &os, const IP_addr &addr) {
  41.     os << int(addr[0]) << '.' << int(addr[1]) << '.' << int(addr[2]) << '.' << int(addr[3]);
  42.     return os;
  43. }

  44. struct IP_subnet {
  45.     IP_addr subnet_base;
  46.     int mask_len;
  47.    
  48.     size_t size() const {
  49.         // .0 and .255 are not valid IP address unless it's a single address subnet
  50.         if (mask_len==32) {
  51.             return 1;
  52.         }
  53.         return (~subnet_mask(mask_len)) + 1 - 2;
  54.     }
  55.    
  56.     IP_addr operator[](size_t index) {
  57.         if(mask_len==32)
  58.             return IP_addr{static_cast<uint32_t>(subnet_base.data+index)};
  59.         return IP_addr{static_cast<uint32_t>(subnet_base.data+index+1)};
  60.     }
  61.    
  62.     template<typename Iterator>
  63.     static IP_subnet parse(Iterator begin, Iterator end) {
  64.         IP_subnet ret{0, 0};
  65.         Iterator slash=std::find(begin, end, '/');
  66.         ret.subnet_base=IP_addr::parse(begin, slash);
  67.         ret.mask_len=0;
  68.         ++slash;
  69.         while(slash!=end) {
  70.             ret.mask_len *= 10;
  71.             ret.mask_len += *slash - '0';
  72.             ++slash;
  73.         }
  74.         ret.subnet_base=ret.subnet_base.mask(ret.mask_len);
  75.         return ret;
  76.     }
  77. };

  78. template<typename InputContainer, typename OutputContainer>
  79. size_t random_pick(InputContainer input, OutputContainer &output) {
  80.     size_t n=input.size();
  81.     size_t k=output.size();
  82.     k=std::min(n, k);
  83.     for (size_t i=0; i<k; i++) {
  84.         output[i]=input[i];
  85.     }
  86.     std::random_device rd;
  87.     std::default_random_engine e(rd());
  88.    
  89.     for (size_t i=k; i<n; i++) {
  90.         size_t j=std::uniform_int_distribution<size_t>(0, i+1)(e);
  91.         if(j<k)
  92.             output[j]=input[i];
  93.     }
  94.     return k;
  95. }

  96. inline std::ostream &operator << (std::ostream &os, const IP_subnet &subnet) {
  97.     os << subnet.subnet_base << '/' << subnet.mask_len;
  98.     return os;
  99. }

  100. int main(int argc, const char * argv[]) {
  101.     std::string ip("192.168.2.234");
  102.     IP_addr addr=IP_addr::parse(ip.begin(), ip.end());
  103.     std::cout << addr << std::endl;
  104.     std::string ip_subnet("192.168.2.58/24");
  105.     // parse会自动将这个子网修正为192.168.2.0/24
  106.     IP_subnet sn=IP_subnet::parse(ip_subnet.begin(), ip_subnet.end());
  107.     std::cout <<sn << std::endl;
  108.     std::cout <<sn[0] << std::endl;
  109.     std::vector<IP_addr> out(20);
  110.     random_pick(sn, out);
  111.     std::cout << "---------------------\n";
  112.     for(auto &&e: out) {
  113.         std::cout << e << std::endl;
  114.     }
  115.     return 0;
  116. }
复制代码

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
5 [报告]
发表于 2015-10-17 01:53 |只看该作者
如果需要在多个网段中随机挑选,用下面这段:

  1. struct IP_subnet_set {
  2.     std::vector<IP_subnet> data;
  3.    
  4.     size_t size() const {
  5.         size_t ret=0;
  6.         for(auto && sn : data) {
  7.             ret += sn.size();
  8.         }
  9.         return ret;
  10.     }
  11.    
  12.     void add_subnet(const IP_subnet &sn) {
  13.         data.push_back(sn);
  14.     }
  15.    
  16.     struct const_iterator {
  17.         const IP_subnet_set *owner=nullptr;
  18.         size_t sn_index=0;
  19.         size_t ip_index=0;
  20.         const_iterator(const IP_subnet_set *p)
  21.         : owner(p)
  22.         , sn_index(0)
  23.         , ip_index(0)
  24.         {}
  25.         
  26.         const_iterator(const IP_subnet_set *p, size_t sni, size_t ipi)
  27.         : owner(p)
  28.         , sn_index(sni)
  29.         , ip_index(ipi)
  30.         {}
  31.         
  32.         void next() {
  33.             if(sn_index>=owner->data.size()) { owner=nullptr; return; }
  34.             ip_index++;
  35.             if(ip_index==owner->data[sn_index].size()) {
  36.                 ip_index=0;
  37.                 sn_index++;
  38.             }
  39.         }
  40.         
  41.         bool ended() const {
  42.             return (!owner)
  43.             || (sn_index>=owner->data.size())
  44.             || ((sn_index==owner->data.size()-1) && (ip_index==owner->data[sn_index].size()));
  45.         }
  46.         
  47.         const_iterator operator++() {
  48.             next();
  49.             return *this;
  50.         }
  51.         
  52.         IP_addr operator*() const {
  53.             return owner->data[sn_index][ip_index];
  54.         }
  55.         
  56.         bool operator==(const const_iterator &other) const {
  57.             return (ended()&&other.ended())
  58.             || (owner==other.owner && sn_index==other.sn_index && ip_index==other.ip_index);
  59.         }
  60.         
  61.         bool operator!=(const const_iterator &other) const {
  62.             return !operator==(other);
  63.         }
  64.     };
  65.    
  66.     const_iterator begin() const {
  67.         return const_iterator(this);
  68.     }
  69.    
  70.     const_iterator end() const {
  71.         return const_iterator(nullptr);
  72.     }
  73.    
  74.     template<typename OutputContainer>
  75.     size_t random_pick(OutputContainer &output) {
  76.         size_t n=size();
  77.         size_t k=output.size();
  78.         k=std::min(n, k);
  79.         const_iterator it=begin();
  80.         for (size_t i=0; i<k; i++, ++it) {
  81.             output[i]=*it;
  82.         }
  83.         std::random_device rd;
  84.         std::default_random_engine e(rd());
  85.         
  86.         for (size_t i=k; i<n; i++, ++it) {
  87.             size_t j=std::uniform_int_distribution<size_t>(0, i+1)(e);
  88.             if(j<k) output[j]=*it;
  89.         }
  90.         return k;
  91.     }
  92. };
复制代码
使用方法:

  1.     IP_subnet_set sns;
  2.     sns.add_subnet(IP_subnet::parse("192.168.2.58/24"));
  3.     sns.add_subnet(IP_subnet::parse("192.168.18.58/24"));
  4.     sns.add_subnet(IP_subnet::parse("10.0.0.0/16"));
  5.     std::vector<IP_addr> out(200);
  6.     sns.random_pick(out);
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP