简体   繁体   English

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

[英]Int division: Why is the result of 1/3 == 0?

I was writing this code:我正在写这段代码:

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

The result is 0. Why is this, and how do I solve this problem?结果是0。这是为什么,我该如何解决这个问题?

The two operands (1 and 3) are integers, therefore integer arithmetic (division here) is used.两个操作数(1 和 3)是整数,因此使用整数算术(这里是除法)。 Declaring the result variable as double just causes an implicit conversion to occur after division .将结果变量声明为 double 只会导致在除法之后发生隐式转换。

Integer division of course returns the true result of division rounded towards zero.整数除法当然返回四舍五入到零的除法的真实结果。 The result of 0.333... is thus rounded down to 0 here.因此0.333...的结果在此处向下舍入为 0。 (Note that the processor doesn't actually do any rounding, but you can think of it that way still.) (请注意,处理器实际上并没有进行任何舍入,但您仍然可以这样想。)

Also, note that if both operands (numbers) are given as floats;另外,请注意,如果两个操作数(数字)都以浮点数形式给出; 3.0 and 1.0, or even just the first , then floating-point arithmetic is used, giving you 0.333... . 3.0 和 1.0,或者甚至只是第一个,然后使用浮点运算,给你0.333...

1/3 uses integer division as both sides are integers. 1/3使用整数除法,因为两边都是整数。

You need at least one of them to be float or double .您至少需要其中一个为floatdouble

If you are entering the values in the source code like your question, you can do 1.0/3 ;如果您像您的问题一样在源代码中输入值,您可以执行1.0/3 the 1.0 is a double. 1.0是双倍的。

If you get the values from elsewhere you can use (double) to turn the int into a double .如果您从其他地方获取值,则可以使用(double)int转换为double

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

Explicitly cast it as a double明确地将其转换为double

double g = 1.0/3.0

This happens because Java uses the integer division operation for 1 and 3 since you entered them as integer constants.发生这种情况是因为 Java 对13使用整数除法运算,因为您将它们作为整数常量输入。

Because you are doing integer division.因为你正在做整数除法。

As @Noldorin says, if both operators are integers, then integer division is used.正如@Noldorin 所说,如果两个运算符都是整数,则使用整数除法。

The result 0.33333333 can't be represented as an integer, therefore only the integer part (0) is assigned to the result.结果 0.33333333 不能表示为整数,因此仅将整数部分 (0) 分配给结果。

If any of the operators is a double / float , then floating point arithmetic will take place.如果任何运算符是double / float ,则将进行浮点运算。 But you'll have the same problem if you do that:但是如果你这样做,你会遇到同样的问题:

int n = 1.0 / 3.0;

The easiest solution is to just do this最简单的解决方案就是这样做

double g = (double) 1 / 3;

What this does, since you didn't enter 1.0 / 3.0, is let you manually convert it to data type double since Java assumed it was Integer division, and it would do it even if it meant narrowing the conversion.由于您没有输入 1.0 / 3.0,因此您可以手动将其转换为数据类型 double,因为 Java 假定它是整数除法,即使这意味着缩小转换范围,它也会这样做。 This is what is called a cast operator.这就是所谓的强制转换运算符。 Here we cast only one operand, and this is enough to avoid integer division (rounding towards zero)这里我们只转换一个操作数,这足以避免整数除法(向零舍入)

The result is 0. Why is this, and how do I solve this problem?结果为 0。这是为什么,我该如何解决这个问题?

TL;DR TL;博士

You can solve it by doing:您可以通过以下方式解决它:

double g = 1.0/3.0; 

or或者

double g = 1.0/3; 

or或者

double g = 1/3.0; 

or或者

double g = (double) 1 / 3;

The last of these options is required when you are using variables eg int a = 1, b = 3; double g = (double) a / b;当您使用变量时,最后一个选项是必需的,例如int a = 1, b = 3; double g = (double) a / b; int a = 1, b = 3; double g = (double) a / b; . .

A more completed answer更完整的答案

double g = 1 / 3;双 g = 1 / 3;

This result in 0 because这导致0因为

  • first the dividend < divisor;首先是除数<除数;
  • both variables are of type int therefore resulting in int ( 5.6.2. JLS ) which naturally cannot represent the a floating point value such as 0.333333.. .这两个变量都是int类型,因此导致int ( 5.6.2. JLS ) 自然不能表示浮点值,例如0.333333..
  • "Integer division rounds toward 0." “整数除法向 0 舍入。” 15.17.2 JLS 15.17.2 JLS

Why double g = 1.0/3.0;为什么要double g = 1.0/3.0; and double g = ((double) 1) / 3;double g = ((double) 1) / 3; work?工作?

From Chapter 5. Conversions and Promotions one can read:第 5 章。转换和促销可以阅读:

One conversion context is the operand of a numeric operator such as + or *.一种转换上下文是数字运算符的操作数,例如 + 或 *。 The conversion process for such operands is called numeric promotion.此类操作数的转换过程称为数值提升。 Promotion is special in that, in the case of binary operators, the conversion chosen for one operand may depend in part on the type of the other operand expression.提升的特殊之处在于,在二元运算符的情况下,为一个操作数选择的转换可能部分取决于另一个操作数表达式的类型。

and 5.6.2. Binary Numeric Promotion5.6.2. Binary Numeric Promotion 5.6.2. Binary Numeric Promotion

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:当运算符将二进制数值提升应用于一对操作数时,每个操作数都必须表示一个可转换为数值类型的值,以下规则按顺序适用:

If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).如果任何操作数属于引用类型,则将对其进行拆箱转换(第 5.1.8 节)。

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:加宽原语转换(第 5.1.2 节)适用于转换以下规则指定的一个或两个操作数:

If either operand is of type double, the other is converted to double.如果任一操作数是 double 类型,则另一个操作数将转换为 double。

Otherwise, if either operand is of type float, the other is converted to float.否则,如果任一操作数的类型为浮点型,则另一个将转换为浮点型。

Otherwise, if either operand is of type long, the other is converted to long.否则,如果任一操作数是 long 类型,则另一个将转换为 long。

Otherwise, both operands are converted to type int.否则,两个操作数都转换为 int 类型。

you should use你应该使用

double g=1.0/3;

or或者

double g=1/3.0;

Integer division returns integer.整数除法返回整数。

The conversion in JAVA is quite simple but need some understanding. JAVA中的转换非常简单,但需要一些了解。 As explain in the JLS for integer operations :正如 JLS 中对整数运算的解释:

If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long.如果除移位运算符以外的整数运算符至少有一个 long 类型的操作数,则使用 64 位精度执行运算,并且数值运算符的结果为 long 类型。 If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).如果另一个操作数不长,则首先将其扩展(第 5.1.5 节)以通过数字提升(第 5.6 节)键入 long。

And an example is always the best way to translate the JLS ;)一个例子总是翻译 JLS 的最佳方式;)

int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)

Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int.否则,使用 32 位精度执行运算,数值运算符的结果为 int 类型。 If either operand is not an int, it is first widened to type int by numeric promotion.如果任一操作数不是 int,则首先通过数字提升将其扩展为 int 类型。

short + int -> int + int -> int

A small example using Eclipse to show that even an addition of two short s will not be that easy :一个使用 Eclipse 的小例子表明即使添加两个short也不是那么容易:

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

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

This will required a casting with a possible loss of precision.这将需要一个可能会损失精度的铸件。

The same is true for the floating point operators 浮点运算符也是如此

If at least one of the operands to a numerical operator is of type double, then the operation is carried out using 64-bit floating-point arithmetic, and the result of the numerical operator is a value of type double.如果数值运算符的至少一个操作数是 double 类型,则使用 64 位浮点算术执行运算,数值运算符的结果是 double 类型的值。 If the other operand is not a double, it is first widened (§5.1.5) to type double by numeric promotion (§5.6).如果另一个操作数不是双精度数,则首先将其扩展(第 5.1.5 节)以通过数字提升(第 5.6 节)键入双精度数。

So the promotion is done on the float into double.所以促销是在浮动上完成的。

And the mix of both integer and floating value result in floating values as said如前所述,整数和浮点值的混合导致浮点值

If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other is integral.如果二元运算符的至少一个操作数是浮点类型,则该运算是浮点运算,即使另一个是整数。

This is true for binary operators but not for "Assignment Operators" like +=这适用于二元运算符,但不适用于像+=这样的“赋值运算符”

A simple working example is enough to prove this一个简单的工作示例足以证明这一点

int i = 1;
i += 1.5f;

The reason is that there is an implicit cast done here, this will be execute like原因是这里进行了隐式转换,这将像执行

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

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

Because it treats 1 and 3 as integers, therefore rounding the result down to 0, so that it is an integer.因为它将 1 和 3 视为整数,因此将结果向下舍入为 0,因此它是整数。

To get the result you are looking for, explicitly tell java that the numbers are doubles like so:要获得您正在寻找的结果,请明确告诉 java 数字是双精度数,如下所示:

double g = 1.0/3.0;

Make the 1 a float and float division will be used将 1 设为浮点数,将使用浮点除法

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

I did this.我这样做了。

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

Use .0 while doing double calculations or else Java will assume you are using Integers.在进行双重计算时使用 .0,否则 Java 会假定您使用的是整数。 If a Calculation uses any amount of double values, then the output will be a double value.如果计算使用任意数量的双精度值,则输出将是双精度值。 If the are all Integers, then the output will be an Integer.如果都是整数,则输出将是整数。

(1/3) means Integer division, thats why you can not get decimal value from this division. (1/3) 表示整数除法,这就是为什么你不能从这个除法中得到十进制值的原因。 To solve this problem use:要解决此问题,请使用:

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

Do "double g=1.0/3.0;"执行“双 g=1.0/3.0;” instead.反而。

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

Since both 1 and 3 are ints the result not rounded but it's truncated.由于 1 和 3 都是整数,因此结果不会四舍五入,但会被截断。 So you ignore fractions and take only wholes.所以你忽略分数而只取整数。

To avoid this have at least one of your numbers 1 or 3 as a decimal form 1.0 and/or 3.0.为避免这种情况,请至少将数字 1 或 3 之一作为十进制形式 1.0 和/或 3.0。

Try this out:试试这个:

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

My code was:我的代码是:

System.out.println("enter weight: ");
int weight = myObj.nextInt();

System.out.println("enter height: ");
int height = myObj.nextInt();

double BMI = weight / (height *height)
System.out.println("BMI is: " + BMI);

If user enters weight(Numerator) = 5, and height (Denominator) = 7, BMI is 0 where Denominator > Numerator & it returns interger (5/7 = 0.71 ) so result is 0 ( without decimal values )如果用户输入体重(分子)= 5,身高(分母)= 7,则 BMI 为 0,其中分母 > 分子,它返回整数(5/7 = 0.71) ,因此结果为 0 (无小数)

Solution :解决方案 :

Option 1:选项1:

doubleouble  BMI = (double) weight / ((double)height * (double)height);

Option 2:选项 2:

double  BMI = (double) weight / (height * height);

I noticed that this is somehow not mentioned in the many replies, but you can also do 1.0 * 1 / 3 to get floating point division.我注意到这在许多回复中都没有提到,但你也可以做1.0 * 1 / 3来获得浮点除法。 This is more useful when you have variables that you can't just add .0 after it, eg当您有不能在其后添加 .0 的变量时,这会更有用,例如

import java.io.*;

public class Main {
    public static void main(String[] args) {
        int x = 10;
        int y = 15;
        System.out.println(1.0 * x / y);
    }
}

Many others have failed to point out the real issue:许多其他人未能指出真正的问题:

An operation on only integers casts the result of the operation to an integer.仅对整数的运算将运算结果转换为整数。

This necessarily means that floating point results, that could be displayed as an integer, will be truncated (lop off the decimal part).这必然意味着可以显示为整数的浮点结果将被截断(去掉小数部分)。

What is casting (typecasting / type conversion) you ask?你问什么是强制转换(类型转换/类型转换)?

It varies on the implementation of the language, but Wikipedia has a fairly comprehensive view, and it does talk about coercion as well, which is a pivotal piece of information in answering your question.它因语言的实现而异,但 Wikipedia 有一个相当全面的观点,它也谈到了强制,这是回答你问题的关键信息。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM