C#中的整型/双精度浮点型转换解释

11

我编写了一些计算代码(下面是我复制的一个非常简化的例子),像CASE2那样,结果很糟糕。像CASE1这样重构代码后,就可以正常工作了。我知道在CASE 2中存在隐式转换,但不确定完整原因。有人能够解释一下下面到底发生了什么吗?

  //CASE 1, result 5.5
    double auxMedia = (5 + 6);
    auxMedia = auxMedia / 2;

    //CASE 2, result 5.0
    double auxMedia1 = (5 + 6) / 2;

    //CASE 3, result 5.5
    double auxMedia3 = (5.0 + 6.0) / 2.0;

    //CASE 4, result 5.5
    double auxMedia4 = (5 + 6) / 2.0;

我猜测CASE2中的/2操作将(5 + 6)强制转换为int类型,导致除法结果向下取整为5,然后再次强制转换为double类型并转换为5.0。

CASE3和CASE4也解决了这个问题。


2
作为附注:这里仅在运行时执行一个操作。即在情况1中的/2。其余都是由编译器完成的。 - Marc Gravell
@Marc:编译器不能完全在编译时执行第一种情况吗?因为auxMedia是本地变量并且被赋予了一个常数。或者这是一种仅由JIT进行的优化吗? - Michael Burr
@Michael - 我会期望这个留给JIT处理。要回答这个问题,你需要查看不同编译器的输出... - Marc Gravell
@Marc - 我在想C#规范是否因某种原因禁止那样的优化。C/C++标准有“好像”规则的整个概念,有时会引起混淆。我可以看出C#设计人员可能希望放弃处理“好像”规则,因为他们可以将这些优化推迟到JIT/运行时。这只是出于好奇而随意闲聊,几乎没有实际适用性(我认为)。 - Michael Burr
4个回答

13
  1. 5 + 6是整数11;然后您将其强制转换为double(在赋值中),再除以2;得到5.5
  2. 5 + 6是整数11;在整数运算下,整数11/2=5,然后在赋值中将其强制转换为double
  3. 5.0 + 6.0是double 11.0;除以double 2.0得到double 5.5
  4. 5 + 6是整数11;在除法时会隐式转换为double 11.0,然后除以double 2.0得到double 5.5

马克是正确的。如果你的第二行是 auxMedia = auxMedia / 2.0,那么你将得到期望的结果,因为 2.0 被读取为 double 类型,而 2 被读取为 int 类型(会丢掉任何小数位 - 甚至不会四舍五入)。 - Jaxidian

5

进一步解释Marc的(正确的)答案,整数被解释为整型,而带有小数点的数字被解释为双精度浮点型。要将一个整数声明为字面量双精度浮点数,请在其后追加“D”:

        //CASE 2b, result 5.5
        double auxMedia2b = (5D + 6D) / 2;

1
//CASE 2, result 5.0
double auxMedia1 = (5 + 6) / 2;

(5 + 6) 操作的结果是整数。因为两个操作数都是整数类型。然后,编译器执行 11 / 2,其中两个操作数也都是整数。最后一次除法的结果显然是 5,因为它是一个整数除法(不知道正确的英语单词)。


1

你是正确的。CASE 2 在赋值之前使用整数算术。你也可以通过进行显式转换来解决这个问题:

double auxMedia1 = ((double) (5 + 6)) / 2;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接