随机数与CompreTo()中的GetHashCode()?

时间:2011-12-13 22:21:17

标签: c# random gethashcode compareto

我在我的struct CompareTo()中使用Random类以相同的概率选择其中一个结构,当它们具有相同的字段值时。使用固定种子实例化Random类以获得可重现的伪随机值序列,以确保无论我使用相同输入运行多少次,我的程序都会给出相同的精确比较结果。

我正在考虑用内存引用或GetHashCode()替换随机数。这样做可以保证:

(1)以相等的概率进行选择,

(2)如果再次运行程序,我会得到相同的结果吗?

struct MyStruct : IComparable<MyStruct>
{
        private readonly float _param1;
        private readonly float _param2;
        private readonly int _randValue;

        public MyStruct(float param1, float param2)
        {
                _param1 = param1;
                _param2 = param2;
                _randValue = _random.Next();
        }

        public int CompareTo(MyStruct other)
        {
            if (_param1 < other._param1)
            {
                return -1;
            }
            else if (_param1 > other._param1)
            {
                return 1;
            }
            else if (_param2 > other._param2)
            {
                return -1;
            }
            else if (_param2 < other._param2)
            {
                return 1;
            }
            // If both params are equal, then select one of the structs with
            // equal probability
            else if (_randValue < other._randValue)
            {
                return -1;
            }
            else if (_randValue > other._randValue)
            {
                return 1;
            }

            return 0;
        }
}

谢谢!

6 个答案:

答案 0 :(得分:16)

  

我在我的struct的CompareTo()中使用Random类以相同的概率选择其中一个结构,当它们具有相同的字段值时。

首先,这是一件非常奇怪的事情。这就像是在说“当我被要求排序一堆数字时,其中两个都是12,我随机选择其中一个为更小”。这并没有任何意义。那两个人是相同的。你没有办法告诉另一个人十二个!

你为什么要做这件奇怪的事?如果这两个值相同,那么说它们是相同的。

在仔细阅读您的代码后,我发现您将随机数保持在结构状态。如果你想做这件奇怪的事情,那就是正确的方法。

我原本以为你随机化比较运算符本身这是一件非常危险的事情。允许排序算法对作为总排序排序的排序采取强依赖性。需要进行比较 才能找到自我一致的总排序。你绝对不能说第一项大于第二项,第二项大于第三项,第三项大于第一项。这违反了比较所要求的传递性,并且当给出不正常的比较操作时,允许排序算法进入无限循环或做任何其他奇怪的行为。

  

我正在考虑用内存引用或GetHashCode()替换随机数。

这是一个更糟糕的主意。 GetHashCode仅对一件事和一件事有用:平衡哈希表。如果您没有平衡哈希表并且调用GetHashCode ,那么您做错了

此外,请仔细考虑。你所处的情况是两个结构否则相等。 合约要求GetHashCode为任何两个比较为的结构返回相同的结果。 GetHashCode显然不是两个相同事物之间消歧的来源!事实上,情况恰恰相反。

  

这是否可以保证选择的概率相等?

不。 GetHashCode不是随机源,也不保证哈希码的分布。

  

如果我再次运行该程序,这是否可以保证我会得到相同的结果?

绝对不是。

答案 1 :(得分:4)

您的代码并不像某些人怀疑的那样危险,因为您在使用数字方面是一致的(它们仅在对象创建时是随机的)。

我看不到的是,为什么在地球上这可以带来任何好处。

考虑没有_randValue的情况。假设你有一个结构(我们称之为x),_param1等于2.0,_param2等于.12,另一个结构(我们称之为y_param1等于2.0,_param2等于.12。

嗯,在xy之间使任何不同的唯一方法就是你已经为他们添加了_randValue

因为它们是结构,它们在任务和拳击之间甚至没有持久的身份。如果我们MyStruct z = x我们没有另一个指向x的指针,那么我们就会有一个全新的MyStruct

除此之外,它没有任何区别。

您的更改的唯一影响是:

  1. 您已为结构的所有情况添加了额外的内存使用量。
  2. 你让排序更加昂贵。
  3. 你的建筑费用更高了。
  4. 您已将构建视为多线程瓶颈,因为您必须锁定Random.Next()
  5. 这些都不可能特别重要,但过早的悲观情绪根本不是很奇怪。

答案 2 :(得分:2)

“Memory Reference”是指结构的地址吗?如果你想要可预测性,那么就不能使用内存地址。

你有什么建议哈希?如果散列结构的属性相等,则散列码也将相等。

我想我很困惑1)为什么Random不适合你2)为什么你不只是调用两个具有相等值的结构“相等”?

答案 3 :(得分:1)

由于Random类正在执行您想要的操作,并且您能够对其进行播种以确保每次都获得相同的值,为什么要更改它?

我不完全确定您打算使用内存引用做什么,但即使您可以指向同一地址并在每次运行代码时看到相同的数据,也无法保证公平分配内存中的值,除非你用随机函数填充它。

散列函数应该返回一个公平的值扩展,但它不是真正的工作工具 - 如果你想要一个随机数,用户一个随机数生成器!

答案 4 :(得分:1)

我个人更喜欢纯粹的随机数,但要回答你的观点:

  1. 是的,这是一个哈希算法,就像md5或sha(虽然这个算法不是专门为你描述的目的而创建的)
  2. ,该值将在程序启动之间持续(@ henk-holterman是正确的,但不保证该值保持不变only for strings
  3. GetHashCode会更快

答案 5 :(得分:0)

我对您的代码的阅读说明您正在使用rand有一个打破平局。我不明白为什么你会想要区分相同的对象,甚至不关心相同对象的顺序。

e.g。在此列表中 -

 A
 B
 B
 C

为什么你会关心或想知道B的哪个实例是第一个?

我建议更好的解决方案是添加对用户有意义的细粒度字段,比如创建日期或修改时间戳。然后你会有一个有意义的打破平局,虽然关系可能仍然存在,我只是觉得它们不会成为问题。