erlang生成N个不重复的随机数

本文介绍了一种基于特定种子生成不重复随机数的方法,并通过Erlang代码实现了该算法。该方法使用种子的元素数量确定进制系统,能够生成指定数量、宽度的随机数,确保了数据的无重复性和乱序性。

生成N个不重复的随机数,比如给定四位数字做种子"0123",

用这个种子的四位数字来表示需要生成的随机数,即相当于

用四进制来表示。

要求生成的数据无重复,乱序,且按格式输出。示例如下:

["0023","0000","0012","0100","0103","0002","0001","0032","0102",
              "0003","0013","0121","0020","0030","0031","0131","0021","0111",
              "0122","0022","0033","0011","0110","0120","0101","0112","0130",
              "0113","0123","0010"]


以下代码以"0123"等标准进制作为种子来实现。如果需要以其它种子来实现,

只需要修改format函数,替换种子即可。

关键参数:Seed, Count, Width

Seed : 种子(根据Seed元素个数来判定进制System)

Count: 需要生成的数字个数

Width : 需要表示的位数,位数不够的前面补0

-module(ct).
-export([test/0, test/3]).
-compile(export_all).

%%test
test()	->
    Seed = "0123",
    Width = 4,
    Count = 30,
    test(Seed, Count, Width).
    
test(Seed, Count, Width)	->
    NL = random_nums(Seed, Count, Width),
    io:format(" format NL:  ~p ~n",[NL]),
    ok.
    
random_nums(Seed, Count, Width) ->
    case is_args_reasonable(Seed, Count, Width) of
	ok ->
	    random_numbers(Seed, Count, Width);
	{error,_} = Reason ->
	    Reason
    end.
    
is_args_reasonable(Seed, Count, Width) ->
    SeedLen = length(Seed),
    LimitWidth = get_limit_width(SeedLen, Count),
    is_args_reasonable(Width, LimitWidth).
is_args_reasonable(Width, LimitWidth) when Width >= LimitWidth ->
      ok;
is_args_reasonable(_Width, _LimitWidth)  ->
      {error, overflow}.
    
get_limit_width(Num, Count) ->
    get_limit_width(Num, Count, 1).
    
get_limit_width(Num, Count, LimitWidth) when Count > Num ->  
    get_limit_width(Num, Count/Num, LimitWidth+1);
get_limit_width(Num, Count, LimitWidth) ->
    LimitWidth.
    
random_numbers(Seed, Count, Width) ->
    L = sub_random_nums(Count),
    format(Seed, Width, shuffle(L)).
    
sub_random_nums(Count) ->
    sub_random_numbers(Count, Count,[]).
sub_random_numbers(Upper, Count, L) when Count > 0 ->
    KV = {get_random(Upper), Count-1},
    sub_random_numbers(Upper, Count-1, [KV|L]);
sub_random_numbers(_Upper, _Count, L)  ->
    L.
get_random(Upper) when is_integer(Upper) ->
    rand(Upper);
get_random(_Upper) ->
    rand(1000000).
get_random() ->
    rand(1000000).
    
rand(Upper) ->
    {N1, N2, N3} = now(),
    No1 = N2 * get_no2(),
    No2 = N3 * get_no1(),
    No3 = N1 * get_no3(),
    {RandomNo, _} = random:uniform_s(Upper,{No1,No2,No3}),
    RandomNo-1.
    
get_no1() ->
    list_to_integer(os:getpid()).
    
get_no2() ->
    {_,_,No3} = os:timestamp(),
    No3.
    
get_no3() ->
    Pids = os:cmd("ps -e"),
    sub_get_no3(Pids, length(Pids), 5, 0).
    
sub_get_no3(_, _, 0, No) -> No;
sub_get_no3(Pids, Len, Count, No) -> 
    Location = random:uniform(get_no2()) rem Len + 1,
    NChar = lists:nth(Location, Pids),
    NNo = case is_integer(NChar) of 
                true ->
                    No + NChar;
                _ ->
                    No + list_to_integer(NChar)
          end,
    sub_get_no3(Pids, Len, Count-1, NNo).
    
shuffle(L) when is_list(L) ->
    {_, NL} = lists:unzip(lists:keysort(1, L)),
    NL.
    
format(Seed, Width, L) when is_list(L) andalso is_integer(Width) ->
    System = integer_to_list(length(Seed)),
    Wid = integer_to_list(Width),
    NL = [lists:flatten(io_lib:format("~"++ Wid ++"." ++ System ++ ".0X", 
			    [X,""])) || X<-L].
    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值