C# 生成随机16位字符串
创建随机16位字符串的更好方法是什么?我已经使用了这段代码,你能推荐一种更有效或更优雅的方法吗C# 生成随机16位字符串,c#,C#,创建随机16位字符串的更好方法是什么?我已经使用了这段代码,你能推荐一种更有效或更优雅的方法吗 static string Random16DigitString() { var rand = new Random(); return $"{rand.Next(100000000).ToString().PadLeft(8, '0')}{rand.Next(100000000).ToString().PadLeft(8, '0')}"; } PS:我这样做的原因是创建一个0.0
static string Random16DigitString() {
var rand = new Random();
return $"{rand.Next(100000000).ToString().PadLeft(8, '0')}{rand.Next(100000000).ToString().PadLeft(8, '0')}";
}
PS:我这样做的原因是创建一个0.0000000000000000格式的字符串,因此我将按以下方式使用它:
var myString = "0." + Random16DigitString();
您的解决方案依赖于字符串操作,这将减慢它的速度 尝试: 这将更快,因为它不依赖于串接或插值等字符串操作。它只是将随机字符插入字符数组,然后将该数组转换为字符串。在我的机器上执行1亿次解决方案大约需要47秒,我的代码大约需要27秒才能产生相同的结果 r、 Next10+48可以在上面的代码中工作,但实际上有点慢。r、 Next48,57更慢
您的代码也可以更简单${rand.next10000000:D8}{rand.next10000000:D8}也会这样做。执行的时间差不多相同。以下是我最后使用的代码:
static readonly Random rnd = new Random();
static string Q() {
// https://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number/768001#768001
// It was decided to use a lock instead of [ThreadStatic] because this api object is designed to be used by many threads simultaneously.
lock (rnd) {
// Get a string representing a positive number greater than 0 and less than 1 with exactly 16 decimal places.
// Original implementation
//return $"0.{rnd.Next(100000000).ToString().PadLeft(8, '0')}{rnd.Next(100000000).ToString().PadLeft(8, '0')}";
// This works but is slow
//return rnd.NextDouble().ToString("F16");
// Found a better faster way: https://stackoverflow.com/questions/48455624/generate-random-16-digit-string/48457354#48457354
var chars = new char[18];
chars[0] = '0';
chars[1] = '.';
for (var i = 2; i < 18; i++)
chars[i] = (char)(rnd.NextDouble() * 10 + 48);
return new string(chars);
}
}
以下是我使用的测试,感谢吉姆·伯格的回答
using System;
using System.Diagnostics;
using System.Text;
namespace NetCoreApp1 {
class Program {
static void Main(string[] args) {
var sync = new object();
var rnd = new Random();
Time("method1", () => {
var value = $"{rnd.Next(100000000).ToString().PadLeft(8, '0')}{rnd.Next(100000000).ToString().PadLeft(8, '0')}";
});
Time("method2", () => {
var value = $"{rnd.Next(100000000):D8}{rnd.Next(100000000):D8}";
});
Time("next double", () => {
var value = rnd.NextDouble().ToString("F16"); // turns out surprisingly slow, even slower than the first two
});
Time("method3", () => {
var v = new char[16];
for (var j = 0; j < 16; j++)
v[j] = (char)(rnd.NextDouble() * 10 + 48); // fastest
var value = new string(v);
});
Time("method3 with lock", () => {
lock (sync) {
var v = new char[16];
for (var j = 0; j < 16; j++)
v[j] = (char)(rnd.NextDouble() * 10 + 48); // a tiny bit slower with the lock
var value = new string(v);
}
});
Time("method4", () => {
var sb = new StringBuilder(16);
for (var j = 0; j < 16; j++)
sb.Append((char)(rnd.NextDouble() * 10 + 48)); // slower than method 3
var value = sb.ToString();
});
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
static void Time(string testName, Action action) {
var sw = Stopwatch.StartNew();
for (var i = 0; i < 10000000; i++)
action();
sw.Stop();
Console.WriteLine($"{testName}: {sw.ElapsedMilliseconds}ms");
}
}
}
你在用这些字符串做什么?首先,你不应该在每次调用中创建一个新的Random实例。将其缓存在ThreadStatic中,或者在其周围有一个带锁的实例。@MarcinJuraszek,我想知道-你有关于该主题的更多信息的链接吗?@jdpenix,我已经更新了这个问题,以显示我正在对该主题做什么strings@bboyle1234看见
using System;
using System.Diagnostics;
using System.Text;
namespace NetCoreApp1 {
class Program {
static void Main(string[] args) {
var sync = new object();
var rnd = new Random();
Time("method1", () => {
var value = $"{rnd.Next(100000000).ToString().PadLeft(8, '0')}{rnd.Next(100000000).ToString().PadLeft(8, '0')}";
});
Time("method2", () => {
var value = $"{rnd.Next(100000000):D8}{rnd.Next(100000000):D8}";
});
Time("next double", () => {
var value = rnd.NextDouble().ToString("F16"); // turns out surprisingly slow, even slower than the first two
});
Time("method3", () => {
var v = new char[16];
for (var j = 0; j < 16; j++)
v[j] = (char)(rnd.NextDouble() * 10 + 48); // fastest
var value = new string(v);
});
Time("method3 with lock", () => {
lock (sync) {
var v = new char[16];
for (var j = 0; j < 16; j++)
v[j] = (char)(rnd.NextDouble() * 10 + 48); // a tiny bit slower with the lock
var value = new string(v);
}
});
Time("method4", () => {
var sb = new StringBuilder(16);
for (var j = 0; j < 16; j++)
sb.Append((char)(rnd.NextDouble() * 10 + 48)); // slower than method 3
var value = sb.ToString();
});
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
static void Time(string testName, Action action) {
var sw = Stopwatch.StartNew();
for (var i = 0; i < 10000000; i++)
action();
sw.Stop();
Console.WriteLine($"{testName}: {sw.ElapsedMilliseconds}ms");
}
}
}