我是一个初学者,而且对我来说没有什么意义。请你能解释一下我哪里出错了。如果以前曾被问过,我很抱歉。
这里小数点的存在意味着使用浮点除法进行评估。
System.out.println(1/3.0); // this prints: 0.3333333333333333
System.out.println(1.0/3); // this prints: 0.3333333333333333
System.out.println(1.0/3.0); // this prints: 0.3333333333333333
显然,下面是"截断整数除法的一个例子。"对我来说似乎有点奇怪但是没问题。
System.out.println(1/3); // this prints: 0
可以说:"在下面一行中,(双)演员阵容被评估为第一名。它有效地说:"将1/3视为双重 - 不要使用截断整数除法。而是使用浮点除法。""
System.out.println((double)1/3); // this prints: 0.3333333333333333
下面,我们得到0.0 - 这是怎么发生的?
System.out.println((double)(1/3)); // this prints: 0.0
好吧也许额外的括号意味着(1/3)得到第一次评估。它是使用截断整数除法得到0来评估的。然后然后应用了双倍给我们0.0好有意义
好的,我们也许可以在这里提出几条一般规则:
规则1 :(双)表达意味着首先应用(双)强制转换,然后评估表达式。
规则2 :( double)(表达式)表示计算表达式然后应用强制转换。 太好了!
所以在下面的下一行我们有:(int)表达式,所以我想我们可以应用规则1)。 (int)演员表被评估为1st。它有效地说:"将1.0 / 3视为一个内存,而不是使用双倍的内存。不要使用浮点除法,而是应用截断整数除法。""所以我们0对吗?否。
System.out.println((int)1/3.0); // this prints: 0.3333333333333333
好的,所以我们有0.33333所以(int)演员表没有被评估为1st。就好像它不在那里。让我们提出第3条规则:
规则3:(int)表达式意味着忽略(int)强制转换只是评估表达式,就像(int)isn甚至那样。
确定将规则3应用到下面的行,我们有(int)但我们只是忽略它。使用浮点除法评估1.0 / 3.0,得到0.3333333。成功了!
System.out.println((int)1.0/3.0); // this prints: 0.3333333333333333
在下面的最后一行中,我们再次(int),但我们只是忽略它。 (1.0 / 3)使用浮点除法得到0.3333333333对吧?否。
System.out.println((int)(1.0/3)); // this prints: 0
好的,现在我很困惑。请你能帮助我解决这个问题吗?
答案 0 :(得分:7)
Java的语言解析规则基本上暗示了代码中的大量括号,这些括号基于操作顺序的规则。了解Java认为括号的位置将有助于您了解此行为。当你说:
(double) 1 / 3.0
......这相当于说:
((double) 1) / 3.0
这意味着1会转换为double,而3.0会自动转换为double,因此您最终会执行浮点除法而不是整数除法。 (double) 1 / 3
会发生同样的情况,因为除数是double
,所以即使被除数是int
,系统也会意识到你想要进行浮点除法。编译器不希望你失去精度,除非你特别要求,所以除非被分红或除数是double
,它将进行double
除法。
另一方面:
(int) 1 / 3.0
......与说法相同:
((int) 1) / 3.0
在这种情况下,你告诉编译器它已经知道的东西:除数(1)是int
。然后你要求它除以double
值(3.0)。由于被除数是double
,它将执行double
除法。
正如您所指出的,1/3
将产生零,因为这是整数除法的工作原理,两个数字都是整数。 1/(int)3.0
会发生同样的情况,因为您告诉编译器在分割发生之前将3.0
变为int
(如1/((int)3.0)
)。
要记住的最后一点是(int) 0.33
也会转换为0
,因为整数不能包含十进制值。因此,当您说(int)(1.0/3)
时,您正在进行double
除法,但之后您将双倍转换为int
,生成0
。
答案 1 :(得分:3)
这在Java Language Specification - Numeric Promotions
中指定如果任何操作数是引用类型,则执行拆箱转换(第5.1.8节)。
然后:
如果任一操作数的类型为double,则另一个操作数转换为double。
否则,如果任一操作数的类型为float,则另一个操作数转换为float。
否则,如果任一操作数的类型为long,则另一个操作数转换为long。
否则,两个操作数都将转换为int类型。
这个概念叫做加宽转换:
5.1.2扩大原始转换
以下19种关于基本类型的特定转换称为扩展基元转换:
- byte to short,int,long,float或double
- 简称为int,long,float或double
- char to int,long,float或double
- int to long,float或double
- 长期漂浮或加倍 浮动加倍
原因
(int) (1.0/3) == 0
是因为你将1.0 / 3的结果(上述规则为0.33333 ...)显式地转换为一个整数,相当于“floor(result)”(向下舍入),因此结果为0。 / p>
Cast的优先级高于/,这就是为什么其他操作误导您的理解:
(double) 1 / 3
将首先显式地将1转换为双值1.0,因此上述规则的结果再次等于0.3333 ....
答案 2 :(得分:2)
在所有这些案件中有两个因素:
我将从你的问题中给出三个例子:
(double) (1/3)
- 首先评估括号中的表达式 - (1/3)是整数除法,结果是0
,然后将其转换为double,得到0.0
(int) (1.0/3)
- 首先评估括号中的表达式 - (1.0 / 3)是浮点除法,因此结果为0.3333
,然后将其转换为int,得到{{1} } 0
变为1.0,然后评估除法(double)1
- 这是浮点除法,因此结果为1.0/3
答案 3 :(得分:2)
演员表仅适用于紧接其后的表达 示例:
(int)1/3
applies the cast to the 1. equivalent to ((int)1)/3
(int)(1/3)
the cast is applied to the result of the expression.
(int)((double)1.333*(float)3.167)
getting a little more complicated. 1.333 casted to double,
multiplied by 3.167 casted to a float, with the result casted to an int
希望有所帮助!