为什么编译器无法告诉结果是一个整数

时间:2014-01-09 10:45:02

标签: c# compiler-construction modulus

我遇到了编译器这个有趣的行为:

如果我有

    public int GetInt()
    {
        Random rnd = new Random();
        double d = rnd.NextDouble();
        int i = d % 1000;

        return i;
    }

我收到错误: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)

实际上有意义,因为1000可以是double,而modulo运算符的结果也可能是double

但是在将代码更改为:

之后
    public int GetInt()
    {
        Random rnd = new Random();
        double d = rnd.NextDouble();
        int i = d % (int)1000;

        return i;
    }

错误仍然存​​在。
据我所知,编译器拥有所有信息,以确定modulo运算符的输出将是int,为什么不编译?

6 个答案:

答案 0 :(得分:5)

如果d是==到1500.72546,则计算结果int d%(int)1000将为500.72546,因此隐式转换为int将导致数据丢失。

答案 1 :(得分:2)

这是设计的。请参阅C#语言规范:

  

7.3.6.2二进制数字促销

     

预定义+的操作数发生二进制数字提升,    - ,*,/,%,&,|,^,==,!=,>,<,> =,和< =二元运算符。二进制   数字促销隐式地将两个操作数转换为通用类型   在非关系运算符的情况下,也成为   结果类型的操作。二进制数字促销包括   按照以下规则应用以下规则:

     

...

     
      
  • 否则,如果任一操作数的类型为double,则另一个操作数将转换为double类型。
  •   

答案 2 :(得分:1)

编译器可以告诉结果这里是一个整数,但是你的朋友。

当然,它可以为你自动转换它,而不是告诉你它,在你的琐碎例子中,这将是正常的。但是,如果将double转换为int意味着数据的 LOSS ,则可能不是您的意图。

如果不是你的意图并且编译器已经完成并为你完成了转换,你可能最终在马拉松调试会话中,没有理智 - 试图弄清楚为什么一个相当深奥的错误报道。

这样,编译器强迫你说,作为程序员,“我知道我会丢失数据,这很好。”​​

答案 3 :(得分:1)

来自文档:

http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx

double的模数结果将是double。如果您需要整数结果,那么您必须:

int i = (int)(d % 1000);

但请记住,您可能会丢失数据。


当我在这里慢慢吸引我的大脑时 - 你的代码没有任何意义。 NextDouble()将返回介于0和1之间的值。您正在执行的操作存在一些逻辑问题,结果将始终为零,例如:

0.15 % 1000 = 0.15

Cast 0.15 to int (always rounds towards zero) -> 0

答案 4 :(得分:1)

编译器会假设您不想松开操作的精度并隐式使用double。

http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx

答案 5 :(得分:1)

  double d = rnd.NextDouble();
  int i = d % (int)1000;

此代码没有意义。 (int)1000表示1000是int,但d % (int)1000表示哦d是双倍的,因此编译器必须将两者转换为另一个答案中提到的公共类型Binary numeric promotions才能使其工作

要理解的一点是,您不能应用任何不同类型的操作,因此如果没有数据丢失,编译器将隐式转换。因此,在应用操作之前,(int)1000 仍会被编译器转换为double。所以结果将是double而不是int