代码之家  ›  专栏  ›  技术社区  ›  Ben Aston

负零(-0)等于C中的零吗#

c#
  •  25
  • Ben Aston  · 技术社区  · 14 年前

    4 回复  |  直到 14 年前
        1
  •  34
  •   Lucero    14 年前

    对于整数,没有二进制表示法可以区分0和-0,因此它们在定义上是相等的。

    对于IEEE浮点数,有正负零的区别。我做了一些测试(CLR的.netframework2.0,C#3),似乎他们被认为是平等的,这实际上是预期的行为根据ieee754标准。

    下面是我的测试代码:

        double minusOne = -1.0;
        double positiveZero = 0.0;
        double negativeZero = minusOne*positiveZero;
        Console.WriteLine("{0} == {1} -> {2}", positiveZero, negativeZero, positiveZero == negativeZero);
        Console.WriteLine("Binary representation is equal: {0}", BitConverter.DoubleToInt64Bits(positiveZero) == BitConverter.DoubleToInt64Bits(negativeZero));
    

    0 == 0 -> True
    Binary representation is equal: False
    
        2
  •  12
  •   Glorfindel Doug L.    4 年前

    对于小数,至少有4种类型的零:

    Decimal zero = Decimal.Zero;
    Decimal negativeZero1 = new Decimal(0, 0, 0, true, 0);
    Decimal negativeZero2 = -0.0m;
    Decimal negativeZero3 = Decimal.Negate(Decimal.Zero);
    

    "0" ,它们有不同的位表示:

    zero:          {0x00000000 00000000 00000000 00000000 }
    negativeZero1: {0x00000000 00000000 00000000 80000000 }
    negativeZero2: {0x00000000 00000000 00000000 80010000 }
    negativeZero3: {0x00000000 00000000 00000000 80000000 }
    

    资料来源: Decimal Negative Zero Representation

        3
  •  8
  •   Matt Tsōnto    7 年前

    这听起来像是你在寻找边缘的情况下,他们是不可互换的,所以这里有一些例子。

    object.Equals struct

    > struct SomeStruct { public double X; }
    > var a = new SomeStruct { X = 0d };
    > var b = new SomeStruct { X = -0d };
    > a.Equals(b)
    false
    >
    

    倒置

    > 1/0d
    ∞
    > 1/-0d
    -∞
    >
    

    任何类型的显式字节或位解构,当然,或类型双关。这些示例来自PC:

    > BitConverter.GetBytes(0d)
    byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }
    > BitConverter.GetBytes(-0d)
    byte[8] { 0, 0, 0, 0, 0, 0, 0, 128 }
    > 
    

    Math.Sign

    数学。符号

    > Math.Sign(-0f)
    0 
    

    Math.Min Math.Max

    一些算术运算有-0的边缘情况 (相当于max),也就是说,当比较有符号的零时,它返回第二个零。所以:

    > BitConverter.GetBytes(Math.Min(0.0, -0.0))
    byte[8] { 0, 0, 0, 0, 0, 0, 0, 128 }
    > BitConverter.GetBytes(Math.Min(-0.0, 0.0))
    byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }
    > 
    

    关于不规则曲线的注记 decimal 陈述

    这个 十进制的

    > new decimal(new int[4] { 0, 0, 0, 0 })
    0
    > new decimal(new int[4] { 0, 0, 0, -2147483648 })
    0
    > 
    

    第二个例子可以认为是一个负零,因为它在位上与常规零相同,除非设置了否定位。但就格式化程序而言,它只是一个零。事实上,有几十种零表示 十进制的 ,对于不同的小数点位移,所有这些位移在算术上相等,并显示为0:

    > new decimal(new int[4] { 0, 0, 0, 131072 })
    0.00
    > new decimal(new int[4] { 0, 0, 0, 1835008 })
    0.0000000000000000000000000000
    > new decimal(new int[4] { 0, 0, 0, 65536 })
    0.0
    

    也就是说,您只能通过二进制比较或二进制转换方式来区分它们。从实验来看 上面的把戏对他们不起作用。 数学。分钟

    奖励:低于正常值的数字

    float double 类型表示 subnormal (又称非规范化)值。我将不深入讨论它们是什么,而是查看链接,但需要知道的重要一点是,CLI规范将它们的操作显式声明为特定于实现的操作。我不 能够 是的。另一方面, 表示它们“被认为是有效的非零值”。