我在我的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;
}
}
谢谢!
答案 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。
嗯,在x
和y
之间使任何不同的唯一方法就是你已经为他们添加了_randValue
。
因为它们是结构,它们在任务和拳击之间甚至没有持久的身份。如果我们MyStruct z = x
我们没有另一个指向x
的指针,那么我们就会有一个全新的MyStruct
。
除此之外,它没有任何区别。
您的更改的唯一影响是:
Random.Next()
。这些都不可能特别重要,但过早的悲观情绪根本不是很奇怪。
答案 2 :(得分:2)
“Memory Reference”是指结构的地址吗?如果你想要可预测性,那么就不能使用内存地址。
你有什么建议哈希?如果散列结构的属性相等,则散列码也将相等。
我想我很困惑1)为什么Random不适合你2)为什么你不只是调用两个具有相等值的结构“相等”?
答案 3 :(得分:1)
由于Random类正在执行您想要的操作,并且您能够对其进行播种以确保每次都获得相同的值,为什么要更改它?
我不完全确定您打算使用内存引用做什么,但即使您可以指向同一地址并在每次运行代码时看到相同的数据,也无法保证公平分配内存中的值,除非你用随机函数填充它。
散列函数应该返回一个公平的值扩展,但它不是真正的工作工具 - 如果你想要一个随机数,用户一个随机数生成器!
答案 4 :(得分:1)
我个人更喜欢纯粹的随机数,但要回答你的观点:
答案 5 :(得分:0)
我对您的代码的阅读说明您正在使用rand
有一个打破平局。我不明白为什么你会想要区分相同的对象,甚至不关心相同对象的顺序。
e.g。在此列表中 -
A
B
B
C
为什么你会关心或想知道B
的哪个实例是第一个?
我建议更好的解决方案是添加对用户有意义的细粒度字段,比如创建日期或修改时间戳。然后你会有一个有意义的打破平局,虽然关系可能仍然存在,我只是觉得它们不会成为问题。