Int除法:为什么1/3 == 0的结果?


107

我在写这段代码:

public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

结果为0。这是为什么,如何解决此问题?

Answers:


147

两个操作数(1和3)是整数,因此使用整数算术(此处为除法)。将结果变量声明为double只会导致除法后发生隐式转换。

当然,整数除法会返回除法四舍五入的真实结果。因此,0.333...此处的结果四舍五入为0。(请注意,处理器实际上不进行任何舍入,但您仍然可以这样考虑。)

另外,请注意,如果两个操作数(数字)均以浮点数给出;3.0和1.0,甚至只是第一个,然后使用浮点运算,就可以得到0.333...


33
+1,并且总是四舍五入。int i = .99999999将int设置为0。更具体地说,它将整数部分并丢弃其余部分。
拜伦·惠特洛克

37
取整为“朝零”,对于大于零的值则为“向下”。(+0.9取整为0,-0.9也取整为0。)
Adrian Smith

@Byron:是的,完全是。我不认为处理器实际上会进行四舍五入,因为除法的实现方式非常不同,但是以这种方式考虑很方便。
Noldorin

15
不,不是四舍五入:截断
罗勒布尔克

3
@BasilBourque用Java术语,舍入DOWN为零。舍入FLOOR是朝负无穷大。
安德烈亚斯

23

1/3 使用整数除法,因为双方都是整数。

您至少需要其中一个是floatdouble

如果您像问题一样在源代码中输入值,则可以执行1.0/3;这1.0是一个双。

如果您从其他地方获取值,则可以使用(double)int转换为double

int x = ...;
int y = ...;
double value = ((double) x) / y;

10

明确将其投射为 double

double g = 1.0/3.0

发生这种情况是因为Java使用整数除法运算,1并且3因为您将它们输入为整数常量。


2

你应该使用

double g=1.0/3;

要么

double g=1/3.0;

整数除法返回整数。


2

因为您正在执行整数除法。

如@Noldorin所说,如果两个运算符都是整数,则使用整数除法。

结果0.33333333不能表示为整数,因此仅将整数部分(0)分配给结果。

如果任何运算符是double/ float,则将进行浮点运算。但是,如果这样做,您将遇到同样的问题:

int n = 1.0 / 3.0;

1

因为它将1和3视为整数,所以将结果舍入为0,因此它是整数。

为了获得您想要的结果,请明确地告诉java数字是两倍,如下所示:

double g = 1.0/3.0;

1

使1成为浮点数并将使用浮点除法

public static void main(String d[]){
    double g=1f/3;
    System.out.printf("%.2f",g);
}

1

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的小例子表明,即使加上两个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节)键入double。

因此,晋升就完成了两次。

整数和浮点值的混合导致浮点值,如所述

如果二进制运算符中的至少一个操作数是浮点类型的,则该运算是浮点运算,即使另一个是整数也是如此。

对于二进制运算符,这是正确的,但对于“赋值运算符”(例如 +=

一个简单的工作示例足以证明这一点

int i = 1;
i += 1.5f;

原因是这里执行了隐式转换,这将像

i = (int) i + 1.5f
i = (int) 2.5f
i = 2

1

1和3是整数竞争者,因此Java进行整数除法,结果为0。如果要编写双精度常量,则必须编写1.0and 3.0


1

最简单的解决方案是执行此操作

double g = ((double) 1 / 3);

既然您没有输入1.0 / 3.0,它所做的就是让您手动将其转换为double类型的数据类型,因为Java假定它是Integer除法,即使它意味着缩小转换范围,它也会这样做。这就是所谓的强制转换运算符。


1

我做到了

double g = 1.0/3.0;
System.out.printf("%gf", g);

在进行双重计算时使用.0,否则Java将假定您正在使用Integers。如果计算使用任意数量的双精度值,则输出将是双精度值。如果全部为Integer,则输出将为Integer。


0

(1/3)表示整数除法,这就是为什么您无法从该除法获得十进制值的原因。要解决此问题,请使用:

public static void main(String[] args) {
        double g = 1.0 / 3;
        System.out.printf("%.2f", g);
    }

0
public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

由于1和3均为整数,因此结果不会四舍五入,但会被截断。因此,您可以忽略分数,只取整数。

为避免这种情况,请至少使用数字1或3中的一个作为小数形式1.0和/或3.0。


0

试试看:

public static void main(String[] args) {
    double a = 1.0;
    double b = 3.0;
    double g = a / b;
    System.out.printf(""+ g);
}

请不要发布仅代码的答案,包括解释代码的功能以及代码如何(以及为什么)解决问题的方法。还要考虑这是一个已有8年历史的问题,并且已有现有的答案,以及您的答案是否比现有的答案有价值?
Mark Rotteveel

-1

进行“ double g = 1.0 / 3.0;” 代替。


只是好奇...这个答案出了什么问题?我第一次遇到问题时就使用了这种方法。对于该解决方案出了什么问题的解释将不胜感激。提前致谢。
Port St Joe先生

@ Mr.PortStJoe它没有向提出问题的人提供任何详细信息。查看评分最高的答案,我们可以看到他们解释了为什么也会发生这种情况。尽管答案在技术上可能是正确的,但其用途可能有限。
Andrew T Finnell

-1

许多其他人未能指出真正的问题:

仅对整数进行的运算会将运算结果转换为整数。

这必然意味着浮点结果(可能显示为整数)将被截断(舍去小数部分)。

您要求的是转换(类型转换/类型转换)?

它在语言的实现上有所不同,但是Wikipedia具有相当全面的观点,并且也谈到了强制性,这是回答问题的关键信息。

http://en.wikipedia.org/wiki/Type_conversion


这个答案是有缺陷的。像一样的全整数形式中都没有涉及类型转换或类型转换1/2,而不是目标语言(java)。您只需调用整数除法,即可得到整数结果。类型转换仅是因为在分配过程中从转换intdouble
YoYo

@YoYo您是说0.5是整数?我不这么认为,亲爱的。
sova

1
这个亲戚没有说什么0.5。简单来说,在Java中1/2是整数除法,结果为零整数。您可以为双精度数分配一个零,尽管它是一个0.0双精度数,但仍将是一个零。
YoYo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.