内部划分:为什么1/3 == 0的结果?

时间:2011-01-13 21:25:37

标签: java integer-division

我写的是这段代码:

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

结果为0.为什么会这样,我该如何解决这个问题?

17 个答案:

答案 0 :(得分:119)

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

整数除法当然会将除法的真实结果舍入为零。因此0.333...的结果向下舍入为0。 (请注意,处理器实际上并没有进行任何舍入,但你可以这样想。)

另请注意,如果两个操作数(数字)都以浮点数给出; 3.0和1.0,或者甚至只是第一个,然后使用浮点运算,为您提供0.333...

答案 1 :(得分:20)

1/3使用整数除法,因为两边都是整数。

您至少需要其中一个floatdouble

如果您在问题的源代码中输入值,则可以执行1.0/3; 1.0是双倍的。

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

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

答案 2 :(得分:10)

明确地将其强制转换为double

double g = 1.0/3.0

这是因为Java使用13的整数除法运算,因为您将它们作为整数常量输入。

答案 3 :(得分:2)

你应该使用

double g=1.0/3;

double g=1/3.0;

整数除法返回整数。

答案 4 :(得分:2)

因为你正在进行整数除法。

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

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

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

int n = 1.0 / 3.0;

答案 5 :(得分:1)

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

要获得您正在寻找的结果,请明确告诉java这些数字是双倍的:

double g = 1.0/3.0;

答案 6 :(得分:1)

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

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

答案 7 :(得分:1)

1和3是整数常量,因此Java执行整数除法,其结果为0.如果要编写双常量,则必须编写1.03.0。< / p>

答案 8 :(得分:1)

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的一个小例子,表明即使添加两个short也不会那么容易:

short s = 1;
s = s + s; <- Compiling error

//possible loss of precision
//  required: short
//  found:    int

这将需要一个可能会损失精度的铸件。

floating point operators

也是如此
  

如果数值运算符的至少一个操作数是double类型,则使用64位浮点运算执行运算,并且数值运算符的结果是double类型的值。如果另一个操作数不是double,则首先将其扩展(第5.1.5节)以通过数字提升(第5.6节)键入double。

所以促销是在浮动上完成的。

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

  

如果二元运算符的至少一个操作数是浮点类型,则操作是浮点运算,即使另一个是整数。

二元运算符也是如此,但+=

之类的“赋值运算符”则不然

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

int i = 1;
i += 1.5f;

原因是这里有一个隐式转换,这将像

一样执行
i = (int) i + 1.5f
i = (int) 2.5f
i = 2

答案 9 :(得分:1)

最简单的解决方案就是做到这一点

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

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

答案 10 :(得分:1)

我做到了

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

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

答案 11 :(得分:1)

<块引用>

结果是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..
  • "整数除法向 0 舍入。" 15.17.2 JLS

为什么 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。

否则,如果任一操作数是 float 类型,则转换另一个 漂浮。

否则,如果任一操作数是 long 类型,则转换另一个 很长。

否则,两个操作数都将转换为 int 类型。

答案 12 :(得分:0)

(1/3)表示整数除法,这就是为什么你不能从这个除法得到十进制值。要解决此问题,请使用:

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

答案 13 :(得分:0)

</html>

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

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

答案 14 :(得分:-1)

“双g = 1.0 / 3.0;”代替。

答案 15 :(得分:-1)

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

  

仅对整数进行的操作会将操作结果强制转换为整数。

这必然意味着可以显示为整数的浮点结果将被截断(从小数部分中删除)。

你问的是什么是投射(类型转换/类型转换)?

它在语言的实现方面有所不同,但维基百科有一个相当全面的观点,它也会讨论强制,这是回答你问题的关键信息。

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

答案 16 :(得分:-1)

尝试一下:

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