2
Vector <float> .Equals应该是自反的还是应该遵循IEEE 754语义?
比较浮点值是否相等时,有两种不同的方法: NaN不等于自身,这符合IEEE 754规范。 NaN等于自身,这提供了自反性的数学属性,这对于定义等价关系至关重要 在C#(内置的IEEE浮点类型float和double)遵循IEEE语义==和!=(和关系运算符一样<),但确保反思object.Equals,IEquatable<T>.Equals(和CompareTo)。 现在考虑一个在float/ 之上提供矢量结构的库double。这样的向量类型将重载==/ !=并覆盖object.Equals/ IEquatable<T>.Equals。 大家都同意==/ !=应该遵循IEEE语义。问题是,这样的库是否应该以Equals自反的方式或与IEEE语义相匹配的方式来实现该方法(与相等运算符分开)。 将IEEE语义用于Equals以下方面的参数: 遵循IEEE 754 (可能更快),因为它可以利用SIMD指令 我已经在stackoverflow上问了一个独立的问题,关于如何使用SIMD指令表达自反式相等性及其性能影响:用于浮点相等性比较的SIMD指令 更新:似乎可以使用三个SIMD指令有效地实现自反性相等。 Equals涉及浮点的文档不需要反射: 对于Equals(Object)方法的所有实现,以下语句必须为true。在列表中x,y和z代表对象引用不为空。 x.Equals(x)返回true,除非涉及浮点类型。参见ISO / IEC / IEEE 60559:2011,信息技术-微处理器系统-浮点运算。 如果您将浮点数用作字典键,那么您将生活在一种罪过的状态中,不应期望表现出理智的行为。 自反的观点: 这是与现有的类型,包括一致的Single,Double,Tuple和System.Numerics.Complex。 我不知道BCL中Equals遵循IEEE而不是反身的任何先例。相反的例子包括Single,Double,Tuple和System.Numerics.Complex。 Equals主要用于依赖自反性的容器和搜索算法。对于这些算法,如果阻止它们工作,则性能提升是无关紧要的。不要牺牲性能的正确性。 它打破了所有基于散列集和词典,Contains,Find,IndexOf各种收藏品/ LINQ,一套基于LINQ操作(Union,Except,等),如果数据中包含NaN的值。 在IEEE语义可接受的情况下执行实际计算的代码通常适用于具体类型并使用==/ !=(或更可能是epsilon比较)。 您目前无法使用泛型编写高性能的计算,因为您需要为此进行算术运算,但是这些不能通过接口/虚拟方法使用。 因此,较慢的Equals方法不会影响大多数高性能代码。 对于需要IEEE语义或需要提高性能的情况,可以提供一种IeeeEquals方法或一种方法IeeeEqualityComparer<T>。 我认为这些论点强烈支持反身执行。 微软的CoreFX团队计划在.NET中引入这种向量类型。与我不同,他们更喜欢IEEE解决方案,主要是因为性能方面的优势。由于这样的决定在最终发布后肯定不会改变,因此我想从社区中获得我认为是一个大错误的反馈。