16

我正在尝试使用 Erlang 生成一个随机的字母数字 ID。我天真地尝试crypto:strong_rand_bytes(Bytes)生成一个随机二进制文件,然后像创建它一样使用该二进制文件<<"my_unique_random_id">>- 这不起作用,因为随机位不一定是有效的 UTF-8 字符串,对吧?

好吧,我在 erlang 文档和其他地方寻找其他选项,但我没有找到任何东西。有人可以指出我的解决方案吗?

4

6 回答 6

18

这可能取决于您需要的随机性。Erlang 的crypto模块产生比模块更强的随机数据random(另见[erlang-questions] Yaws 安全警报 - Yaws 1.93这个问题)。如果你想用来strong_rand_bytes生成一个 ID,也许得到它的 base64 可能就足够了:

> base64:encode(crypto:strong_rand_bytes(Bytes)).

如果需要,您可以将其转换为列表。

于 2012-10-09T07:35:28.123 回答
12

根据在 Erlang 中生成随机字符串,只需几行 Erlang 即可从一组字符生成指定长度的字符串。

get_random_string(Length, AllowedChars) ->
    lists:foldl(fun(_, Acc) ->
                        [lists:nth(random:uniform(length(AllowedChars)),
                                   AllowedChars)]
                            ++ Acc
                end, [], lists:seq(1, Length)).

博客文章对代码进行了逐行解释。查看评论以获取一些优化技巧。

于 2012-10-08T20:20:52.447 回答
4

我已经准备了小模块,
它也使用crypto:rand_uniform/2但没有过时random:uniform

module(cloud_rnd).

-export([rnd_chars/1, rnd_numbers/1, rnd_chars_numbers/1]).

rnd_chars(L)         -> get_rnd(L, chars).
rnd_numbers(L)       -> get_rnd(L, numbers).
rnd_chars_numbers(L) -> get_rnd(L, chars_numbers).

get_rnd(L, chars)         -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz");
get_rnd(L, numbers)       -> gen_rnd(L, "1234567890");
get_rnd(L, chars_numbers) -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz1234567890").

gen_rnd(Length, AllowedChars) ->
  MaxLength = length(AllowedChars),
  lists:foldl(
    fun(_, Acc) -> [lists:nth(crypto:rand_uniform(1, MaxLength), AllowedChars)] ++ Acc end,
    [], lists:seq(1, Length)
  ).
于 2015-06-04T14:19:20.593 回答
2

对各种“我需要随机字符串”问题(无论使用何种语言)的回答的问题是几乎每个解决方案都使用有缺陷的规范,即字符串长度。这些问题本身很少揭示为什么需要随机字符串,但我会大胆假设它们将用作需要唯一的标识符。

有两种主要的方法来获取严格唯一的字符串:确定性(不是随机的)和存储/比较(这是繁重的)。该怎么办?放弃鬼。改为使用概率唯一性。也就是说,接受您的字符串不是唯一的(尽管很小)风险。这就是理解碰撞概率和熵有帮助的地方。

因此,我将改写我的大胆假设,因为您需要一些重复风险很小的标识符。作为一个具体的例子,假设您需要 500 万个重复风险小于万亿分之一的 Id。那么你需要多长的字符串呢?好吧,这个问题没有详细说明,因为它取决于所使用的字符。但更重要的是,它被误导了。您需要的是字符串熵的规范,而不是它们的长度。

这就是EntropyString可以提供帮助的地方。

Bits = entropy_string:bits(5.0e6, 1.0e12).
83.37013046707142
entropy_string:random_string(Bits).
<<"QDrjGQFGgGjJ4t9r2">>

还有其他预定义的字符集,您也可以指定自己的字符(尽管出于效率原因,仅支持具有 2 个字符的幂的集)。最重要的是,在指定数量的字符串中重复的风险是明确的。不再猜测字符串长度。

于 2017-09-01T21:06:42.557 回答
1
randchar(N) ->
   randchar(N, []).

randchar(0, Acc) ->
   Acc;
randchar(N, Acc) ->
   randchar(N - 1, [random:uniform(26) + 96 | Acc]).
于 2012-10-17T04:50:23.003 回答
0

uef_bin:random_latin_binary/2您可以从这里 使用函数: https ://github.com/DOBRO/uef-lib#uef_binrandom_latin_binary2

Bin = uef_bin:random_latin_binary(Length, any)

然后,如果你需要一个string()类型:

String = erlang:binary_to_list(Bin)
于 2019-05-02T12:30:25.227 回答