我想取一个字符串并从0-9生成一个数字。我得到的数字不是必须可预测的,但相同的字符串必须始终生成相同的数字。
我最初的想法是只做string.GetHashCode()并从代码中取最后一位数字。
如果我这样做,我(a)是否会保证总是以相同的数字为同一个字符串结束,并且我(b)最终会在0-9之间合理均匀地分配数字?
或者,是否有更好的方法来实现我想要的目标?
答案 0 :(得分:8)
这应该可以解决问题 - 我将此用于 deterministic 模拟:
public static long GetDeterministicId(string m)
{
return (long) m.ToCharArray().Select((c, i) => Math.Pow(i, c%5)*Math.Max(Math.Sqrt(c), i)).Sum();
}
修改强>
如果您只想要数字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;
}
我已经用英语(https://gist.github.com/deekayen/4148741#file-1-1000-txt)运行了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
足够接近均匀分布!
答案 1 :(得分:2)
对于一种非常“低技术”的方法,哪里不如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
你得到的数字肯定会是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 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
答案 2 :(得分:0)
有很多方法可以实现此功能。例如,您可以将剩下的除法除以所有字符总和的10。
public static int HashString(string str)
{
if(string.IsNullOrEmpty(str)) return 0;
return str.ToCharArray().Sum(c => (int)c) % 10;
}
答案 3 :(得分:0)
我是否(a)保证总是以相同的数字结束 相同的字符串[?]
没有。正如评论中提到的B,GetHashCode的值是一个实现细节,不一定是consistent,例如跨不同版本的.NET。你最好自己编写自己的函数。
简单校验和怎么样?
public static int CheckSum(string s)
{
int sum = 0;
foreach (char c in s)
{
sum = (sum + c)%10;
}
return sum;
}