【问题标题】:Int division: Why is the result of 1/3 == 0?int除法:为什么1/3 == 0的结果?
【发布时间】: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


    【解决方案1】:

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

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

    另外,请注意,如果 两个 操作数(数字)都以浮点数形式给出; 3.0 和 1.0,或者甚至只是 first,然后使用浮点运算,给你0.333...

    【讨论】:

    • +1 并且它总是向下取整。 int i = .99999999 将 int 设置为 0。更具体地说,它采用整数部分并丢弃其余部分。
    • 它“向零”舍入,对于大于零的值,“向下”。 (+0.9 舍入为 0,-0.9 也舍入为 0。)
    • @Byron:是的,没错。我不相信处理器实际上会进行任何舍入,因为除法的实现方式非常不同,但这样想很方便。
    • 不,不是四舍五入:Truncation
    • @BasilBourque 在 Java 术语中,rounding DOWN 接近于零。舍入 FLOOR 是向负无穷大。
    【解决方案2】:

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

    您至少需要其中一个是floatdouble

    如果您像您的问题一样在源代码中输入值,您可以这样做 1.0/31.0 是双精度的。

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

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

    【讨论】:

      【解决方案3】:

      将其显式转换为 double

      double g = 1.0/3.0
      

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

      【讨论】:

        【解决方案4】:

        因为你在做整数除法。

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

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

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

        int n = 1.0 / 3.0;
        

        【讨论】:

          【解决方案5】:

          最简单的解决方案就是这样做

          double g = (double) 1 / 3;
          

          由于您没有输入 1.0 / 3.0,因此您可以手动将其转换为数据类型 double,因为 Java 假定它是整数除法,即使这意味着缩小转换范围,它也会这样做。这就是所谓的强制转换运算符。 这里我们只转换一个操作数,这足以避免整数除法(向零舍入)

          【讨论】:

            【解决方案6】:

            你应该使用

            double g=1.0/3;
            

            double g=1/3.0;
            

            整数除法返回整数。

            【讨论】:

              【解决方案7】:

              结果为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。

              否则,如果任一操作数为浮点类型,则转换另一个 浮动。

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

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

              【讨论】:

                【解决方案8】:

                因为它把 1 和 3 当作整数,所以将结果向下舍入到 0,所以它是一个整数。

                要获得您正在寻找的结果,请明确告诉 java 数字是双精度数,如下所示:

                double g = 1.0/3.0;
                

                【讨论】:

                  【解决方案9】:

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

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

                  【讨论】:

                    【解决方案10】:

                    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
                    

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

                    floating point operators 也是如此

                    如果数值运算符的至少一个操作数是 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
                    

                    【讨论】:

                      【解决方案11】:

                      1 和 3 是整数常量,因此 Java 会进行整数除法,结果为 0。如果要编写双精度常量,则必须编写 1.03.0

                      【讨论】:

                        【解决方案12】:

                        我这样做了。

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

                        在进行双重计算时使用 .0,否则 Java 会假定您使用的是整数。如果计算使用任意数量的双精度值,则输出将是双精度值。如果都是整数,则输出将是整数。

                        【讨论】:

                          【解决方案13】:

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

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

                          【讨论】:

                            【解决方案14】:
                            public static void main(String[] args) {
                                double g = 1 / 3;
                                System.out.printf("%.2f", g);
                            }
                            

                            由于 1 和 3 都是整数,因此结果不会四舍五入,但会被截断。所以你忽略分数而只取整数。

                            为避免这种情况,请至少将数字 1 或 3 之一作为十进制形式 1.0 和/或 3.0。

                            【讨论】:

                              【解决方案15】:

                              试试这个:

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

                              【讨论】:

                              • 请不要发布仅代码的答案,包括说明您的代码的作用以及它如何(以及为什么)解决问题的问题。还要考虑到这是一个已有 8 年历史的问题,它有现有的赞成答案,以及您的答案是否比现有答案增加了任何价值。
                              【解决方案16】:

                              执行“双 g=1.0/3.0;”而是。

                              【讨论】:

                              • 只是好奇......这个答案有什么问题?当我第一次遇到问题时,我使用了这种方法。对此解决方案有什么问题的解释将不胜感激。提前致谢。
                              • @Mr.PortStJoe 它没有向提出问题的人提供任何详细信息。查看评分最高的答案,我们可以看到他们也解释了为什么会发生这种情况。虽然答案在技术上可能是正确的,但它的用处可能被视为有限。
                              【解决方案17】:

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

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

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

                              你问什么是casting(类型转换/类型转换)?

                              它因语言的实现而异,但 Wikipedia 有一个相当全面的观点,它也谈到了强制,这是回答您问题的关键信息。

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

                              【讨论】:

                              • 这个答案有缺陷。在像1/2 这样的全整数定义中不涉及类型转换或类型转换,而不是在目标语言 (java) 中。您只需调用一个整数除法,这将产生一个整数结果。类型转换只是因为在分配期间从int 向上转换为double
                              • @YoYo 你是说 0.5 是一个整数?我不这么认为,伙计。
                              • 这个兄弟没有说任何关于0.5的事情。简单地说,在 Java 中,1/2 是一个整数除法,结果是零整数。您可以将零分配给双精度,它仍然是零,尽管是 0.0 双精度。
                              猜你喜欢
                              • 2021-11-17
                              相关资源
                              最近更新 更多