我想要一个永远唯一的数字,我想出了下面的代码,它生成一个数字,并添加一个校验位到它的结尾,我想知道这个代码有多可靠?
public void GenerateUniqueNumber(out string ValidUniqueNumber) {
string GeneratedUniqueNumber = "";
// Default implementation of UNIX time of the current UTC time
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string FormatedDateTime = Convert.ToInt64(ts.TotalSeconds).ToString();
string ssUniqueId = DateTime.UtcNow.ToString("fffffff");
//Add Padding to UniqueId
string FormatedUniqueId = ssUniqueId.PadLeft(7, '0');
if (FormatedDateTime.Length == 10 && FormatedUniqueId.Length == 7)
{
// Calculate checksum number using Luhn's algorithm.
int sum = 0;
bool odd = true;
string InputData = FormatedDateTime + FormatedUniqueId;
int CheckSumNumber;
for (int i = InputData.Length - 1; i >= 0; i--)
{
if (odd == true)
{
int tSum = Convert.ToInt32(InputData[i].ToString()) * 2;
if (tSum >= 10)
{
string tData = tSum.ToString();
tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
}
sum += tSum;
}
else
sum += Convert.ToInt32(InputData[i].ToString());
odd = !odd;
}
//CheckSumNumber = (((sum / 10) + 1) * 10) - sum;
CheckSumNumber = (((sum + 9) / 10) * 10) - sum;
// Compute Full length 18 digit UniqueNumber
GeneratedUniqueNumber = FormatedDateTime + FormatedUniqueId + Convert.ToString(CheckSumNumber);
}
else
{
// Error
GeneratedUniqueNumber = Convert.ToString(-1);
}
ValidUniqueNumber = GeneratedUniqueNumber;
}
**EDIT:**不能使用澄清GUID,需要通过电话键盘将号码输入IVR系统。
9条答案
按热度按时间kupeojn61#
您不能使用GUID,但是您可以创建类似GUID的own的唯一数字,它基于机器的MAC地址(空间)和当前时间和日期(时间)。如果所有机器都有同步的时钟,这就保证了唯一性。
有关详细信息,请参阅here
pxiryf3j2#
为什么不直接用
Guid
呢?xj3cbfub3#
此方法有几个问题:
ts.TotalSeconds
舍入到0.0000001。所有的转换和毫秒计算都是不必要的。57hvy0tb4#
如果我对您的实现理解正确的话,它只使用当前日期/时间作为基础。这意味着如果您同时创建两个ID,它们将不是唯一的。
klh5stk15#
由于您提到(在注解中)ID存储在DB中,因此您可以使用您提到的方法或随机生成ID,并检查DB中是否存在ID。
如果它已经存在,则生成一个新的,否则就完成了。
但是有一点,我会确保在事务中检查ID的存在性并将记录实际保存到DB,否则您将面临在检查ID和创建行之间有另一个请求创建该记录的风险。
同样只是检查一下,为什么数据库本身生成的自动递增数字不起作用呢?DB会保证它的唯一性(无论如何,对于那个表)
qmelpv7a6#
你没有说这些号码是用来做什么的,它们是否有某种价值与之相关?如果用户能搞清楚方案,猜出有效的票号,会不会有问题?
如果重要的是这些数字很难猜测,这个方案福尔斯了;你可以用一个单调递增的序列号并用一个分组密码(64位的分组大小)加密它;这将提供一个64位的输出或大约20位十进制数字,您可以取(比如)的最后18位。(如果可逆性很重要,即给定一个票证编号,您希望能够恢复序列号,则需要在此处更加小心。)
你是否需要一个100%的保证,保证所有的票号都不会是相同的?如果是这样,你需要把它们保存在一个数据库中,并在使用它们时将它们标记出来。如果你这样做了,那么使用一个好的随机数生成器并每次检查是否有重复的票号可能是合理的。
inn6fuwd7#
使用系统时间是一个很好的开始,但是如果需要同时生成两个UID,就会产生冲突。使用“fffffff”格式也没有帮助:Windows的时钟分辨率只有15-16毫秒,所以那些“f“中只有一两个有什么好处。
此外,您的方法会告诉您ID是何时产生的。根据您的需求,这可能是您想要的功能,也可能是安全性风险。
除了时间之外,您还需要在ID中包含其他信息。一些可能的选择包括:
如果你想 * 确保 * 唯一性,那么把你的ID存储在一个数据库中,这样你就可以检查重复。
wgeznvg78#
正如“Andrew Hare”所说,你可以使用Guid。关于你的代码,答案是“NO”!因为如果客户端计算机的日期时间是错误的,或者更改结果可能是两个或更多!
3wabscal9#
反正没有随机这回事。我有个建议。
1.创建您自己的“随机”18位数字
1.在将其发送给用户之前,请根据DB中的现有数据进行检查
1.如果已经在DB中,冲洗并重复。