我遇到了编译器这个有趣的行为:
如果我有
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
,为什么不编译?
答案 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。
答案 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
。