【发布时间】:2011-06-08 19:10:03
【问题描述】:
我正在编写这段代码:
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
结果为0。这是为什么,我该如何解决这个问题?
【问题讨论】:
标签: java integer-division
我正在编写这段代码:
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
结果为0。这是为什么,我该如何解决这个问题?
【问题讨论】:
标签: java integer-division
两个操作数(1 和 3)是整数,因此使用整数算术(这里是除法)。将结果变量声明为 double 只会导致在除法之后发生隐式转换。
整数除法当然会返回四舍五入到零的除法结果。 0.333... 的结果因此在此处向下舍入为 0。 (请注意,处理器实际上并没有进行任何舍入,但您仍然可以这样想。)
另外,请注意,如果 两个 操作数(数字)都以浮点数形式给出; 3.0 和 1.0,或者甚至只是 first,然后使用浮点运算,给你0.333...。
【讨论】:
int i = .99999999 将 int 设置为 0。更具体地说,它采用整数部分并丢弃其余部分。
DOWN 接近于零。舍入 FLOOR 是向负无穷大。
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 假定它是整数除法,即使这意味着缩小转换范围,它也会这样做。这就是所谓的强制转换运算符。 这里我们只转换一个操作数,这足以避免整数除法(向零舍入)
【讨论】:
你应该使用
double g=1.0/3;
或
double g=1/3.0;
整数除法返回整数。
【讨论】:
结果为0。这是为什么,我该如何解决这个问题?
TL;DR
您可以通过以下方式解决它:
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; 有效?
来自Chapter 5. Conversions and Promotions 可以阅读:
一个转换上下文是数字运算符的操作数,例如 + 要么 *。这种操作数的转换过程称为数字 晋升。促销的特殊之处在于,在二进制的情况下 运算符,为一个操作数选择的转换可能部分取决于 另一个操作数表达式的类型。
和5.6.2. Binary Numeric Promotion
当一个运算符将二进制数字提升应用于一对 操作数,每个操作数必须表示一个可转换为 数字类型,按顺序适用以下规则:
如果任何操作数是引用类型,则对其进行拆箱 转换(第 5.1.8 节)。
加宽基元转换(第 5.1.2 节)用于转换或 两个操作数均由以下规则指定:
如果任一操作数是 double 类型,则另一个将转换为 double。
否则,如果任一操作数为浮点类型,则转换另一个 浮动。
否则,如果任一操作数是 long 类型,则转换另一个 长。
否则,两个操作数都转换为 int 类型。
【讨论】:
因为它把 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 中的转换很简单,但需要一些了解。正如 integer operations 的 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 的小例子表明即使添加两个 shorts 也不是那么容易:
short s = 1;
s = s + s; <- Compiling error
//possible loss of precision
// required: short
// found: int
这将需要一个可能会损失精度的铸件。
如果数值运算符的至少一个操作数是 double 类型,则使用 64 位浮点算术执行运算,数值运算符的结果是 double 类型的值。如果另一个操作数不是双精度,则首先将其扩展(第 5.1.5 节)以通过数字提升(第 5.6 节)键入双精度。
所以提升是在 float 到 double 上完成的。
并且整数和浮点值的混合导致浮动值,如所述
如果二元运算符的至少一个操作数是浮点类型,则该运算是浮点运算,即使另一个是整数。
这适用于二元运算符,但不适用于像 += 这样的“赋值运算符”
一个简单的工作示例就足以证明这一点
int i = 1;
i += 1.5f;
原因是这里做了一个隐式转换,这将像执行一样
i = (int) i + 1.5f
i = (int) 2.5f
i = 2
【讨论】:
1 和 3 是整数常量,因此 Java 会进行整数除法,结果为 0。如果要编写双精度常量,则必须编写 1.0 和 3.0。
【讨论】:
我这样做了。
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;”而是。
【讨论】:
许多其他人未能指出真正的问题:
仅对整数的运算将运算结果转换为整数。
这必然意味着可以显示为整数的浮点结果将被截断(去掉小数部分)。
你问什么是casting(类型转换/类型转换)?
它因语言的实现而异,但 Wikipedia 有一个相当全面的观点,它也谈到了强制,这是回答您问题的关键信息。
【讨论】:
1/2 这样的全整数定义中不涉及类型转换或类型转换,而不是在目标语言 (java) 中。您只需调用一个整数除法,这将产生一个整数结果。类型转换只是因为在分配期间从int 向上转换为double。
0.5的事情。简单地说,在 Java 中,1/2 是一个整数除法,结果是零整数。您可以将零分配给双精度,它仍然是零,尽管是 0.0 双精度。