我正在写这段代码:
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
结果为 0。这是为什么,我该如何解决这个问题?
我正在写这段代码:
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
结果为 0。这是为什么,我该如何解决这个问题?
两个操作数(1 和 3)是整数,因此使用整数算术(这里是除法)。将结果变量声明为 double 只会导致在除法之后发生隐式转换。
整数除法当然返回四舍五入到零的除法的真实结果。因此,这里的结果0.333...
向下舍入为 0。(请注意,处理器实际上并没有进行任何舍入,但您仍然可以这样想。)
另外,请注意,如果两个操作数(数字)都以浮点数形式给出;3.0 和 1.0,或者甚至只是第一个,然后使用浮点运算,给你0.333...
.
1/3
使用整数除法,因为两边都是整数。
您至少需要其中一个为float
或double
。
如果您像您的问题一样在源代码中输入值,您可以这样做1.0/3
;这1.0
是一个双。
如果您从其他地方获取值,您可以使用它(double)
来int
将double
.
int x = ...;
int y = ...;
double value = ((double) x) / y;
明确地将其转换为double
double g = 1.0/3.0
发生这种情况是因为 Java 使用整数除法运算,1
并且3
因为您将它们作为整数常量输入。
因为你正在做整数除法。
正如@Noldorin 所说,如果两个运算符都是整数,则使用整数除法。
结果 0.33333333 不能表示为整数,因此仅将整数部分 (0) 分配给结果。
如果任何运算符是double
/ float
,则将进行浮点运算。但是如果你这样做,你会遇到同样的问题:
int n = 1.0 / 3.0;
最简单的解决方案就是这样做
double g = (double) 1 / 3;
由于您没有输入 1.0 / 3.0,因此您可以手动将其转换为数据类型 double,因为 Java 假定它是整数除法,即使这意味着缩小转换范围,它也会这样做。这就是所谓的强制转换运算符。这里我们只转换一个操作数,这足以避免整数除法(向零舍入)
结果为 0。这是为什么,我该如何解决这个问题?
TL;博士
您可以通过以下方式解决它:
double g = 1.0/3.0;
或者
double g = 1.0/3;
或者
double g = 1/3.0;
或者
double g = (double) 1 / 3;
当您使用变量时,这些选项中的最后一个是必需的,例如int a = 1, b = 3; double g = (double) a / b;
.
更完整的答案
双 g = 1 / 3;
这导致0
因为
int
因此导致int
(5.6.2.JLS)自然不能表示浮点值,例如0.333333..
.为什么double g = 1.0/3.0;
和 double g = ((double) 1) / 3;
工作?
从第 5 章。转换和促销可以阅读:
一种转换上下文是数字运算符的操作数,例如 + 或 *。此类操作数的转换过程称为数值提升。提升的特殊之处在于,在二元运算符的情况下,为一个操作数选择的转换可能部分取决于另一个操作数表达式的类型。
和5.6.2. Binary Numeric Promotion
当运算符将二进制数值提升应用于一对操作数时,每个操作数都必须表示一个可转换为数值类型的值,以下规则按顺序适用:
如果任何操作数属于引用类型,则将对其进行拆箱转换(第 5.1.8 节)。
加宽原语转换(第 5.1.2 节)适用于转换以下规则指定的一个或两个操作数:
如果任一操作数是 double 类型,则另一个操作数将转换为 double。
否则,如果任一操作数的类型为浮点型,则另一个将转换为浮点型。
否则,如果任一操作数是 long 类型,则另一个将转换为 long。
否则,两个操作数都转换为 int 类型。
你应该使用
double g=1.0/3;
或者
double g=1/3.0;
整数除法返回整数。
1 和 3 是整数常量,因此 Java 进行整数除法,结果为 0。如果要编写双精度常量,则必须编写1.0
and 3.0
。
因为它将 1 和 3 视为整数,因此将结果向下舍入为 0,因此它是整数。
要获得您正在寻找的结果,请明确告诉 java 数字是双精度数,如下所示:
double g = 1.0/3.0;
将 1 设为浮点数,将使用浮点除法
public static void main(String d[]){
double g=1f/3;
System.out.printf("%.2f",g);
}
JAVA中的转换非常简单,但需要一些了解。正如 JLS 中对整数运算的解释:
如果除移位运算符以外的整数运算符至少有一个 long 类型的操作数,则使用 64 位精度执行运算,并且数值运算符的结果为 long 类型。如果另一个操作数不长,则首先将其扩展(第 5.1.5 节)以通过数字提升(第 5.6 节)键入 long。
一个例子总是翻译 JLS 的最佳方式;)
int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)
否则,使用 32 位精度执行运算,数值运算符的结果为 int 类型。如果任一操作数不是 int,则首先通过数字提升将其扩展为 int 类型。
short + int -> int + int -> int
一个使用 Eclipse 的小例子表明即使添加两个short
s 也不是那么容易:
short s = 1;
s = s + s; <- Compiling error
//possible loss of precision
// required: short
// found: int
这将需要一个可能会损失精度的铸件。
浮点运算符也是如此
如果数值运算符的至少一个操作数是 double 类型,则使用 64 位浮点运算执行运算,数值运算符的结果是 double 类型的值。如果另一个操作数不是双精度数,则首先将其扩展(第 5.1.5 节)以通过数字提升(第 5.6 节)键入双精度数。
所以促销是在浮动上完成的。
如前所述,整数和浮点值的混合导致浮点值
如果二元运算符的至少一个操作数是浮点类型,则该运算是浮点运算,即使另一个是整数。
这适用于二元运算符,但不适用于“赋值运算符”,例如+=
一个简单的工作示例足以证明这一点
int i = 1;
i += 1.5f;
原因是这里进行了隐式转换,这将像执行
i = (int) i + 1.5f
i = (int) 2.5f
i = 2
我这样做了。
double g = 1.0/3.0;
System.out.printf("%gf", g);
在进行双重计算时使用 .0,否则 Java 会假定您使用的是整数。如果计算使用任意数量的双精度值,则输出将是双精度值。如果都是整数,则输出将是整数。
(1/3) 表示整数除法,这就是为什么你不能从这个除法中得到十进制值的原因。要解决此问题,请使用:
public static void main(String[] args) {
double g = 1.0 / 3;
System.out.printf("%.2f", g);
}
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
由于 1 和 3 都是整数,因此结果不会四舍五入,但会被截断。所以你忽略分数而只取整数。
为避免这种情况,请至少将数字 1 或 3 之一作为十进制形式 1.0 和/或 3.0。
试试这个:
public static void main(String[] args) {
double a = 1.0;
double b = 3.0;
double g = a / b;
System.out.printf(""+ g);
}
执行“双 g=1.0/3.0;” 反而。
许多其他人未能指出真正的问题:
仅对整数的运算将运算结果转换为整数。
这必然意味着可以显示为整数的浮点结果将被截断(去掉小数部分)。
你问什么是强制转换(类型转换/类型转换)?
它因语言的实现而异,但 Wikipedia 有一个相当全面的观点,它也谈到了强制,这是回答你问题的关键信息。