我正在尝试在C#中创建一个随机字符串生成器,给定字符串的长度。我的第一次尝试是这样的:
public static string RandomString(int characters)
{
string s = "";
for (int i = 0; i < characters; i++)
{
s += Convert.ToChar((97 + r.Next(26)));
}
return s;
}
但是 k 之前字母的频率非常低,所以我试着通过编写自己的随机函数来改变它:
public static string RandomString(int characters)
{
string s = "";
for (int i = 0; i < characters; i++)
{
int randomLetter = 0;
for (int bit = 0; i < 5; bit++)
{
if (r.Next(2) == 0)
continue;
randomLetter += 1 << bit;
if (randomLetter + (1 << (bit + 1)) > 26)
break;
}
s += Convert.ToChar(97 + randomLetter);
}
return s;
}
但有时randomLetter会大于26,有时候太大了。我找不到这个问题的原因,可以吗?
答案 0 :(得分:3)
如果您只想要一个简单的随机字符串,这种方法应该更简单:
private static Random random = new Random();
public static string GetRandomString(int length)
{
var chars = new char[length];
var possibleLetters = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < length; i++)
{
chars[i] = possibleLetters[random.Next(0, possibleLetters.Length - 1)];
}
return new string(chars);
}
我刚用你的代码对我的控制台进行了测试:
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
string s = RandomString(10000);
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
sw.Restart();
for (int i = 0; i < 1000; i++)
{
string s = GetRandomString(10000);
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
Console.Read();
结果:
RandomString => 18830,7537
GetRandomString => 321.098
正如您所看到的,您的实现不仅更糟糕,而且执行速度也慢得多。
为了证明好奇心,我用StringBuilder重新创建了我的方法:
private static string GetRandomStringSB(int length)
{
var stringBuilder = new StringBuilder(length);
var possibleLetters = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < length; i++)
{
stringBuilder.Append(possibleLetters[r.Next(0, possibleLetters.Length - 1)]);
}
return stringBuilder.ToString();
}
毫不奇怪,结果并没有太多推迟:
RandomString (OP) => 13175
GetRandomString (char[]) => 213
GetRandomStringSB (StringBuilder) => 244
答案 1 :(得分:2)
为什么所有这些按位算术?首先,让我们说明问题:
我想生成
characters
长度的随机字符串;该字符串应包含a
..z
应该有均匀分布
实施起来很简单:
// Simplest, but not thread safe
private static Random s_Random = new Random();
// Not thread safe
public static string RandomString(int characters) {
if (characters < 0)
throw new ArgumentOutOfRangeException("characters");
StringBuilder sb = new StringBuilder(characters);
// I personally, prefer Linq + Concat, but let's preserve the loop
for (int i = 0; i < characters; ++i) {
char c = (char)(s_Random.Next('z' - 'a' + 1) + 'a'); // +1 - 'z' should be included
sb.Append(c);
}
return sb.ToString();
}
Linq 版本更短,但可能更少可读:
// Not thread safe
public static string RandomString(int characters) {
if (characters < 0)
throw new ArgumentOutOfRangeException("characters");
return string.Concat(Enumerable
.Range(0, characters)
.Select(i => (char)(s_Random.Next('z' - 'a' + 1) + 'a')));
}
测试:
Console.Write(RandomString(10));
结果(可能会有所不同):
dcdwwvzhnz
最后,让我们看一下实际的发布&#34; ...但的频率 >之前> strong> k
非常低 ..&#34;
int count = 1000; // we examine "count" random string
int length = 10; // each of "length" length
var distribution = String
.Concat(Enumerable.Range(1, count).Select(i => RandomString(length)))
.GroupBy(c => c, (k, s) => new {
key = k,
freq = (double)s.Count() / length / count
})
.OrderBy(item => item.freq)
.Select(item => $"{item.key}: {item.freq:F4}")
.ToArray();
Console.Write(string.Join(Environment.NewLine, distribution));
结果(可能会有所不同):没有证据这样的倾斜
p: 0.0351
a: 0.0359
r: 0.0360
y: 0.0362
l: 0.0363
z: 0.0364
n: 0.0369
u: 0.0370
h: 0.0371
e: 0.0373
c: 0.0375
v: 0.0376
x: 0.0376
o: 0.0380
q: 0.0380
m: 0.0388
k: 0.0389
d: 0.0391
s: 0.0391
g: 0.0396
w: 0.0401
b: 0.0406
t: 0.0406
f: 0.0422
i: 0.0434
j: 0.0447
答案 2 :(得分:0)
使用这些方法,您可以指定有效字符,或接受所有字符。
public static string RandomString(int len)
{
var array = Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue + 1).Select(x => (char)x).ToArray();
return RandomString(len, array);
}
private static string RandomString(int len, char[] array)
{
Random r = new Random();
StringBuilder sb = new StringBuilder();
while (sb.Length < len)
sb.Append(array[r.Next(array.Length-1)]);
return sb.ToString();
}
答案 3 :(得分:0)
这是一个简单的函数,可以生成随机字符串
.once()
答案 4 :(得分:0)
如果你想随机。
private static System.Security.Cryptography.RandomNumberGenerator random = System.Security.Cryptography.RandomNumberGenerator.Create();
public static string Random(int characters)
{
var data = new byte[characters];
random.GetBytes(data);
return data.Select(b=>Convert.ToChar((int)(96 + (Math.Floor((b/(double)byte.MaxValue)*27)) - 1))).Aggregate(new System.Text.StringBuilder(),(a,c) => a.Append(c)).ToString();
}
请注意,这不是快速而是随机的
答案 5 :(得分:-3)
感谢@Evk我明白了。我最后的方法:
public static string RandomString(int characters)
{
string s = "";
for (int i = 0; i < characters; i++)
{
int ascii = 0;
for (int bit = 0; bit < 5; bit++)
{
if (r.Next(2) == 0)
continue;
ascii += 1 << bit;
if (ascii + (1 << (bit + 1)) > 25)
break;
}
s += Convert.ToChar(97 + ascii);
}
return s;
}