繁体   English   中英

Java 算术 int 与 long

[英]Java arithmetic int vs. long

我在谷歌上做了一些搜索,但似乎找不到我要找的东西。 我试图找出一些关于 Java 中算术工作方式的详细信息。 例如,如果您将两个 long 相加,这是否使用与将两个 int 相加时使用的相同加法运算符? 此外,当你在这样的算术表达式中混合 longs 和 ints 时,引擎盖下发生了什么:

long result;
long operand a = 1;
int operand b = 999999999;

result = a + b;

如果有人可以对此有所了解或发布相关文章的链接,那就太棒了。 谢谢!

编辑:感谢您到目前为止的答复。 此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?

混合类型时,int 会自动加宽为 long,然后将两个 long 相加以产生结果。 Java 语言规范解释了包含不同原始类型的操作的过程。

具体来说,这些是每个原始类型将扩展到而不需要强制转换的类型:

  • 字节到 short、int、long、float 或 double
  • 短到 int、long、float 或 double
  • char 到 int、long、float 或 double
  • int 到 long、float 或 double
  • long 浮动或加倍
  • 浮动到两倍

请参阅: 转换和促销

据此,您的int被提升为long然后被评估。

例如, int + double和其他原语也会发生同样的情况。 IE。

System.out( 1 + 2.0 );// prints 3.0 a double

至于加法运算符, 我几乎是一样的,但我没有任何参考。

快速查看编译器的源代码就会发现它们是不同的。

iadd表示 int 加法,而ladd表示长加法:

请参阅此示例代码:

$cat Addition.java 
public class Addition {
    public static void main( String [] args ) {
        int  a  = Integer.parseInt(args[0]);
        long b = Long.parseLong(args[0]);
        // int addition 
        int  c  = a + a;
        // long addition 
        long d = a + b;
    }
}
$javac Addition.java 
$

编译时生成的字节码是这样的:

$javap -c Addition 
Compiled from "Addition.java"
public class Addition extends java.lang.Object{
public Addition();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   iconst_0
   2:   aaload
   3:   invokestatic    #2; //Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
   6:   istore_1
   7:   aload_0
   8:   iconst_0
   9:   aaload
   10:  invokestatic    #3; //Method java/lang/Long.parseLong:(Ljava/lang/String;)J
   13:  lstore_2
   14:  iload_1
   15:  iload_1
   16:  iadd
   17:  istore  4
   19:  iload_1
   20:  i2l
   21:  lload_2
   22:  ladd
   23:  lstore  5
   25:  return

}

看看第16行它说: iadd (用于 int 加法)而第22行说ladd (用于长加法)

此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?

是的,而且用较小的尺寸执行算术也是“安全的” ,从某种意义上说,它们不会破坏程序,只会丢失信息。

例如,尝试将Integer.MAX_VALUE添加到Integer.MAX_VALUE以查看会发生什么,或者int x = ( int ) ( Long.MAX_VALUE - 1 );

此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?

这取决于你所说的安全是什么意思。 它当然不会避免您需要考虑溢出的可能性。

这称为算术提升。 详情请查看http://www.cafeaulait.org/course/week2/22.html

int a=5;  
long b=10;  
a+=b;  
System.out.println(a);

主要区别在于a = a + b没有进行类型转换,因此编译器会因为您没有进行类型转换而生气。 但是对于a += b ,它真正做的是将b类型转换为与a兼容a类型。

这个简单的例子可以消除java中算术运算时对数据类型转换的疑惑。

    byte a = 1;
    short b = 1;
    System.out.println(a+b);                     //Output = 2
    Object o = a+b;                              //Object becomes int
    System.out.println(o.getClass().getName());  //Output = java.lang.Integer

    int c = 1;
    System.out.println(a+b+c);                   //Output = 3
    o = a+b+c;                                   //Object becomes int
    System.out.println(o.getClass().getName());  //Output = java.lang.Integer

    long d = 1l;
    System.out.println(a+b+c+d);                 //Output = 4
    o = a+b+c+d;                                 //Object becomes long
    System.out.println(o.getClass().getName());  //Output = java.lang.Long

    float e = 1.0f;
    System.out.println(a+b+c+d+e);               //Output = 5.0
    o = a+b+c+d+e;                               //Object becomes float
    System.out.println(o.getClass().getName());  //Output = java.lang.Float

    double f = 1.0;
    System.out.println(a+b+c+d+e+f);             //Output = 6.0
    o = a+b+c+d+e+f;                             //Object becomes double
    System.out.println(o.getClass().getName());  //Output = java.lang.Double

以下是java中根据范围的数据类型顺序:

    byte<short<int<long<float<double

这是扩大发生的顺序。

注意: float 的范围比 long 大,但尺寸更小。

答案指出算术提升。 但考虑到这一点,我陷入了以下陷阱(我很惭愧),我想在这里指出:如果对我来说有两个以上的操作数,似乎计算是从左到右执行的,如果实际有两个,则会发生算术提升焦点中的操作数具有不同的类型。 因此,以下代码对 s1 和 s2 产生不同的结果。 我对此的解释是:在计算 s1 时,首先将 a 和 b 作为两个整数相加(并且发生溢出),然后将 c(a long)的结果相加。 在计算 s2 时,首先添加 c 和 b(如 long),然后添加 a(提升为 long),因此不会发生溢出。

final int a = Integer.MAX_VALUE;
final int b = 1;
final long c = 1L;
final long s1 = a + b + c;
final long s2 = c + b + a;
System.out.println("s1=" + s1 + ", s2=" + s2);

输出将为: s1=-2147483647, s2=2147483649

暂无
暂无

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

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