【问题标题】:Generate integer based on any given string (without GetHashCode)根据任何给定的字符串生成整数(没有 GetHashCode)
【发布时间】:2015-01-08 07:39:30
【问题描述】:

我正在尝试编写一种基于任何给定字符串生成整数的方法。在 2 个相同的字符串上调用此方法时,我需要该方法两次生成完全相同的整数。

我尝试使用 .GetHasCode() 但是,一旦我将项目移动到另一台机器上,这是非常不可靠的,因为 GetHasCode() 会为同一字符串返回不同的值

碰撞率非常低也很重要。到目前为止,我编写的自定义方法仅在几十万条记录后就会产生冲突。

哈希值必须是整数。字符串哈希值(如 md5)会在速度和加载开销方面削弱我的项目。

整数哈希被用于执行极其快速的文本搜索,我已经很好地工作了,但是它目前依赖于 .GetHasCode() 并且在涉及多台机器时不起作用。

任何见解都将不胜感激。

【问题讨论】:

  • 你是否按照here的建议实现了一个众所周知的算法?
  • 对字符串的结构(大小、编码)有什么限制吗?
  • 没有限制,但任何给定的字符串都不会超过一百个字符左右。
  • 您需要一个哈希码,而不是 .NET 的实现(因为它可能会有所不同)。因此,在我看来,您应该研究哈希码实现,以找到适合您需求的实现。如果 .NET 的 GetHashCode() 在其他方面适合您的需求,您甚至可以反编译它(它的某些版本)并将其封装在私有实现中,这样您就知道它不会改变。如果这不起作用,您应该进行研究,然后向 SO 寻求任何可能出现的特定问题的帮助。

标签: c# hash gethashcode


【解决方案1】:

MD5 哈希返回一个字节数组,可以转换为整数:

var mystring = "abcd";
MD5 md5Hasher = MD5.Create();
var hashed = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(mystring));
var ivalue = BitConverter.ToInt32(hashed, 0);

当然,您正在从 128 位散列转换为 32 位 int,因此丢失了一些信息,这将增加冲突的可能性。您可以尝试将第二个参数调整为 ToInt32 以查看 MD5 哈希的任何特定范围是否比其他范围内的数据产生的冲突更少。

【讨论】:

  • 感谢您的回复。这是我几分钟前发现的相同代码的更高效版本。我的方法现在在我的机器和服务器上产生相同的结果。即使 MD5 在我的情况下工作,MD5 会在另一台机器上产生不同的结果吗?
  • @user1691808 md5 与平台无关。对于相同的输入,无论机器/语言如何,它都会产生相同的值。
  • 我学到的另一个注意事项是,mysql BIGINT 始终为 8 个字节,可以存储 -9223372036854775808 到 9223372036854775807,这似乎与您的代码的 Int64 版本将产生的整数范围相同。只是一些我以前不知道的知识。
【解决方案2】:

如果您的哈希码在“几十万条记录之后”创建了重复项,那么您的哈希码实现就相当不错了。

如果您do the math,您会发现 32 位哈希码在大约 70,000 条记录后有 50% 的机会创建重复项。在一百万条记录之后生成重复的概率非常接近确定,以至于无关紧要。

根据经验,当散列的记录数等于可能值数的平方根时,生成重复散列码的可能性为 50%。因此,对于具有 2^32 个可能值的 32 位哈希码,在大约 2^16 (65,536) 个值之后生成重复的机会是 50%。 实际数字略大——接近 70,000——但根据经验法则,您可以大致了解。

另一个经验法则是,当散列的项目数是平方根的四倍时,生成重复项的几率接近 100%。因此,使用 32 位哈希码,您几乎可以保证在仅对 2^18 (262,144) 条记录进行哈希处理后发生冲突。

如果您使用 MD5 并将其从 128 位转换为 32 位,这不会改变。

【讨论】:

    【解决方案3】:

    此代码将任何字符串映射到 0-100 之间的 int

    int x= "ali".ToCharArray().Sum(x => x)%100;
    

    【讨论】:

    • 求和会得到正态分布而不是均匀分布,这会增加碰撞的可能性。
    【解决方案4】:
    using (MD5 md5 = MD5.Create())
    {
        bigInteger = new BigInteger(md5.ComputeHash(Encoding.Default.GetBytes(myString)));
    }
    

    BigInteger 需要 Org.BouncyCastle.Math

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-02
      • 2021-02-02
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多