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

Posted

技术标签:

【中文标题】Int除法:为啥1/3 == 0的结果?【英文标题】:Int division: Why is the result of 1/3 == 0?Int除法:为什么1/3 == 0的结果? 【发布时间】:2021-11-17 19:16:24 【问题描述】:

我正在编写这段代码:

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

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

【问题讨论】:

【参考方案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】:

你应该使用

double g=1.0/3;

double g=1/3.0;

整数除法返回整数。

【讨论】:

【参考方案5】:

因为你在做整数除法。

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

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

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

int n = 1.0 / 3.0;

【讨论】:

【参考方案6】:

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

double g = (double) 1 / 3;

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

【讨论】:

【参考方案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 双精度。

以上是关于Int除法:为啥1/3 == 0的结果?的主要内容,如果未能解决你的问题,请参考以下文章

java做除法运算,为啥除不开时也会得到整数呢

为啥这个计算(除法)会返回错误的结果?

excel2007除法结果为啥只有整数,怎样才能保留两位小数?

为啥这个除法结果为零?

无论结果如何,支持除以零的最快整数除法是啥?

结果错误的除法