gpt4 book ai didi

c# - 谁能用 C# 中的带符号 float 解释这种奇怪的行为?

转载 作者:IT王子 更新时间:2023-10-29 03:28:51 25 4
gpt4 key购买 nike

这是带有注释的示例:

class Program
{
// first version of structure
public struct D1
{
public double d;
public int f;
}

// during some changes in code then we got D2 from D1
// Field f type became double while it was int before
public struct D2
{
public double d;
public double f;
}

static void Main(string[] args)
{
// Scenario with the first version
D1 a = new D1();
D1 b = new D1();
a.f = b.f = 1;
a.d = 0.0;
b.d = -0.0;
bool r1 = a.Equals(b); // gives true, all is ok

// The same scenario with the new one
D2 c = new D2();
D2 d = new D2();
c.f = d.f = 1;
c.d = 0.0;
d.d = -0.0;
bool r2 = c.Equals(d); // false! this is not the expected result
}
}

那么,您对此有何看法?

最佳答案

bug在System.ValueType的下面两行:(我踩到了引用源)

if (CanCompareBits(this)) 
return FastEqualsCheck(thisObj, obj);

(两种方法都是[MethodImpl(MethodImplOptions.InternalCall)])

当所有字段都是 8 字节宽时,CanCompareBits 错误地返回 true,导致对两个不同但语义相同的值进行按位比较。

当至少一个字段不是 8 字节宽时,CanCompareBits 返回 false,代码继续使用反射循环遍历字段并为每个值调用 Equals ,它正确地将 -0.0 视为等于 0.0

这是来自 SSCLI 的 CanCompareBits 的源代码:

FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj)
{
WRAPPER_CONTRACT;
STATIC_CONTRACT_SO_TOLERANT;

_ASSERTE(obj != NULL);
MethodTable* mt = obj->GetMethodTable();
FC_RETURN_BOOL(!mt->ContainsPointers() && !mt->IsNotTightlyPacked());
}
FCIMPLEND

关于c# - 谁能用 C# 中的带符号 float 解释这种奇怪的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2508945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com