如何从C#中的字符串生成非随机数?

如何从C#中的字符串生成非随机数?,c#,.net,C#,.net,我想取一个字符串并从0-9生成一个数字。我得到的数字不一定是可预测的,但相同的字符串必须始终生成相同的数字 我最初的想法是只执行string.GetHashCode()并从代码中提取最后一位数字 如果我这样做了,我(a)是否会保证在同一个字符串中始终使用相同的数字,以及(b)是否会在0-9之间合理地均匀分布数字 或者,有没有更好的方法来实现我想要的呢?这应该可以做到-我用它来进行确定性模拟: 编辑 如果您只想要数字0-9,则进一步mod10: public static long GetDete

我想取一个字符串并从0-9生成一个数字。我得到的数字不一定是可预测的,但相同的字符串必须始终生成相同的数字

我最初的想法是只执行string.GetHashCode()并从代码中提取最后一位数字

如果我这样做了,我(a)是否会保证在同一个字符串中始终使用相同的数字,以及(b)是否会在0-9之间合理地均匀分布数字


或者,有没有更好的方法来实现我想要的呢?

这应该可以做到-我用它来进行确定性模拟:

编辑

如果您只想要数字0-9,则进一步
mod
10:

public static long GetDeterministicId(string m)
{
    return (longg) m.ToCharArray().Select((c, i) => Math.Pow(i, c%5)*Math.Max(Math.Sqrt(c), i)).Sum() % 10;
}
我已经对1000个英语中最常用的单词()进行了测试,0-9的分布如下:

0 -> 156
1 -> 163
3 -> 114
7 -> 79
6 -> 72
9 -> 55
2 -> 128
8 -> 45
5 -> 89
4 -> 99
这并不完美,但还行

编辑2

进一步的测试表明,将第一个模替换为8(即
Math.Pow(i,c%8)*
)可以产生更好的分布:

0 -> 95
1 -> 113
2 -> 148
3 -> 91
4 -> 68
5 -> 92
6 -> 119
7 -> 79
8 -> 99
9 -> 96
编辑3

好的,胜利者是

return (int)m.ToCharArray().Select((c, i) => Math.Pow(i+2, c % 8) * Math.Max(Math.Sqrt(c), i+2)).Sum() % 10;
并且0-9的分布是

0 -> 90
1 -> 96
2 -> 100
3 -> 99
4 -> 97
5 -> 106
6 -> 110
7 -> 90
8 -> 103
9 -> 109
这足够接近均匀分布

对于一种非常“低技术”的方法来说,它没有rbm的答案那么令人印象深刻。。。您可以这样做:

string strEntry = "lol"; //Your String Here
int intNum = (int)strEntry[strEntry.Length - 1]; //To Convert last letter to its numeric equivalent. Jeppe Stig Nielsen's suggestion
intNum = int.Parse(intNum.ToString().Substring(intNum.ToString().Length - 1)); //Get the last digit of the number you got from previous step
string strEntry = "lol";
List<int> intList = new List<int>();
foreach (char c in strEntry)
{
   intList.Add((int)c);
}
int intNum = intList.Sum();
while (intNum.ToString().Length != 1)
{
   intList.Clear();
   foreach (char c in intNum.ToString())
   {
       intList.Add(int.Parse(c.ToString()));
   }
   intNum = intList.Sum();
}
//You can just get the number you required from intNum
你得到的数字肯定在0-9之间,而且永远都是一样的。另外,我想您也很容易理解代码在做什么

或者。。。您可以使用一种稍微奇特的方法,将字符串中每个字母的每个数值相加,然后返回该字母的最后一位:

string strEntry = "lol";
List<int> intList = new List<int>();
foreach (char c in strEntry)
{
   intList.Add((int)c);
}
int intNum = intList.Sum();
intNum = int.Parse(intNum.ToString().Substring(intNum.ToString().Length - 1));
string strengtry=“lol”;
List intList=新列表();
foreach(强度中的字符c)
{
intList.Add((int)c);
}
int intNum=intList.Sum();
intNum=int.Parse(intNum.ToString().Substring(intNum.ToString().Length-1));
如果您不想只使用上面第二个选项中提供的最后一个数字。。。您可以这样做:

string strEntry = "lol"; //Your String Here
int intNum = (int)strEntry[strEntry.Length - 1]; //To Convert last letter to its numeric equivalent. Jeppe Stig Nielsen's suggestion
intNum = int.Parse(intNum.ToString().Substring(intNum.ToString().Length - 1)); //Get the last digit of the number you got from previous step
string strEntry = "lol";
List<int> intList = new List<int>();
foreach (char c in strEntry)
{
   intList.Add((int)c);
}
int intNum = intList.Sum();
while (intNum.ToString().Length != 1)
{
   intList.Clear();
   foreach (char c in intNum.ToString())
   {
       intList.Add(int.Parse(c.ToString()));
   }
   intNum = intList.Sum();
}
//You can just get the number you required from intNum
string strengtry=“lol”;
List intList=新列表();
foreach(强度中的字符c)
{
intList.Add((int)c);
}
int intNum=intList.Sum();
while(intNum.ToString().Length!=1)
{
intList.Clear();
foreach(intNum.ToString()中的字符c)
{
Add(int.Parse(c.ToString());
}
intNum=intList.Sum();
}
//您可以从intNum获取所需的号码

实现此功能的方法有很多。例如,您可以将其余部分除以所有字符之和的10

public static int HashString(string str)
{
   if(string.IsNullOrEmpty(str)) return 0;
   return str.ToCharArray().Sum(c => (int)c) % 10;
}
我(a)是否会被保证永远以相同的数字结束 相同的字符串[?]

不会。正如B在评论中提到的,GetHashCode的值是一个实现细节,不一定是跨.NET的不同版本。您最好编写自己的函数

简单的校验和怎么样

public static int CheckSum(string s)
{
    int sum = 0;
    foreach (char c in s)
    {
        sum = (sum + c)%10;
    }
    return sum;
}

所以你想要像校验和生成器这样的东西?你可以做gethashcode,然后取最后一个数字,并将其转换为ascii,最后一个数字要清楚,当然
gethashcode
是“一致的”(也就是说,对于每个
string
实例和该字符串值,每次都会返回相同的值)在申请过程的生命周期内。因此,当应用程序的特定实例运行时,给定字符串值的哈希值是固定的。如果不是这样的话,
GetHashCode
将毫无用处。但是:如果退出进程,将.NET Framework更新为较新版本,然后再次启动应用程序,则该字符串值在新的BCL版本下可能具有不同的哈希值。我猜,但当您将字符转换为数字时,它将为您提供该字符的ASCII十进制数。这就是这里正在使用的。我也不是直接转换字符串,而是把它们分解成字符。不,不是。转换为int将生成Unicode代码点。对于ASCII/基本拉丁字符,这与ASCII码点相同,但Unicode比ASCII要多得多。好吧,也许我错认为它是ASCII码,但至少它起到了作用。我将删除对ASCII的任何引用。要获取字符串
strEntry
的最后一个
char
(即最后一个UTF-16代码单位),使用索引器更容易,因此
int intNum=strEntry[strEntry.Length-1]