Java 算术 int 与 long
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3073862/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java arithmetic int vs. long
提问by BordrGuy108
I've done some searching on google, but I can't seem to find what I'm looking for. I'm trying to find out some detailed information on the way arithmetic works in Java. For example, if you add two longs together is this using the same addition operator that is used when adding two ints together? Also, what is going on under the hood when you mix longs and ints in arithmetic expressions like this:
我在谷歌上做了一些搜索,但似乎找不到我要找的东西。我试图找出一些关于 Java 中算术工作方式的详细信息。例如,如果您将两个 long 相加,这是否使用与将两个 int 相加时使用的相同加法运算符?此外,当你在这样的算术表达式中混合 longs 和 ints 时,引擎盖下发生了什么:
long result;
long operand a = 1;
int operand b = 999999999;
result = a + b;
If anyone could shed some light on this or post links to relevant articles that would be awesome. Thanks!
如果有人可以对此有所了解或发布相关文章的链接,那就太棒了。谢谢!
EDIT: Thanks for the replies so far. Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
编辑:感谢您到目前为止的答复。此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?
采纳答案by krock
When mixing types the int is automatically widened to a long and then the two longs are added to produce the result. The Java Language Specificationexplains the process for operations containing different primative types.
混合类型时,int 会自动加宽为 long,然后将两个 long 相加以产生结果。在Java语言规范说明了含有不同灵长类动物类型的操作过程。
Specifically, these are the types each primative will widen to without requiring a cast:
具体来说,这些是每个原始类型将扩展到而不需要强制转换的类型:
- byte to short, int, long, float, or double
- short to int, long, float, or double
- char to int, long, float, or double
- int to long, float, or double
- long to float or double
- float to double
- 字节到 short、int、long、float 或 double
- 短到 int、long、float 或 double
- char 到 int、long、float 或 double
- int 到 long、float 或 double
- long 浮动或加倍
- 浮动到两倍
回答by OscarRyz
See: Conversions and promotions
请参阅:转换和促销
According to that, your int
is promoted to long
and then is evaluated.
据此,您将int
被提升long
,然后被评估。
Same happens with, for instance, int
+ double
and the rest of the primitives. ie.
例如,int
+double
和其他原语也会发生同样的情况。IE。
System.out( 1 + 2.0 );// prints 3.0 a double
As for the addition operator I'm pretty much it is the same, but I don't have any reference of it.
至于加法运算符,我几乎是一样的,但我没有任何参考。
A quick view to the compiler's source reveals they are different.
快速查看编译器的源代码就会发现它们是不同的。
Namely iadd
for int addition and ladd
for long addition:
即iadd
对于整数加法和ladd
长加法:
See this sample code:
请参阅此示例代码:
$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
$
When compiled the byte code generated is this:
编译时生成的字节码是这样的:
$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
}
Look at line 16
it says: iadd
( for int addition ) while the line 22
says ladd
( for long addition )
看看16
它说的行:(iadd
对于整数加法)而行22
说ladd
(对于长加法)
Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?
Yes, and it's also "safe"to perform arithmetic with smaller sizes, in the sense, they don't break the program, you just lose information.
是的,而且 用较小的尺寸执行算术也是“安全的”,从某种意义上说,它们不会破坏程序,只会丢失信息。
For instance, try adding Integer.MAX_VALUEto Integer.MAX_VALUE
to see what happens, or int x = ( int ) ( Long.MAX_VALUE - 1 );
例如,尝试将是Integer.MAX_VALUE来Integer.MAX_VALUE
看看会发生什么,或int x = ( int ) ( Long.MAX_VALUE - 1 );
回答by Stephen C
Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?
It depends what you mean by safe. It certainly won't avoid you needing to consider the possibility of overflow.
这取决于你所说的安全是什么意思。它当然不会避免您需要考虑溢出的可能性。
回答by Aravind Yarram
this is called arithmetic promotion. for details look at http://www.cafeaulait.org/course/week2/22.html
这称为算术提升。详情请查看http://www.cafeaulait.org/course/week2/22.html
回答by Naresh Kumar
int a=5;
long b=10;
a+=b;
System.out.println(a);
The main difference is that with a = a + b
, there is no typecasting going on, and so the compiler gets angry at you for not typecasting.
But with a += b
, what it's really doing is typecasting b
to a
type compatible with a
.
主要区别在于,a = a + b
没有进行类型转换,因此编译器会因为您不进行类型转换而生气。但是对于a += b
,它真正做的是b
将a
类型转换为与a
.
回答by Sahib Bajaj
This simple example could clear the doubts about data type conversion in case of arithmetic operations in java.
这个简单的例子可以消除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
Following is the order of data types according to range in java:
以下是java中根据范围的数据类型顺序:
byte<short<int<long<float<double
This is the order in which widening will happen.
这是扩大发生的顺序。
Note: float has more range than long, but has smaller size.
注意: float 的范围比 long 大,但尺寸更小。
回答by afi65
The answers point out to arithmetic promotion. But with that in mind I trapped into the following pitfall (shame on me) which I want to point out here: If there are more than two operands to me it seems that calculation is performed left to right and arithmetic promotion occurs if the actual two operands in focus have a differnt type. Thus the following code produces different results for s1 and s2. My explanation to this is: When calculating s1 first a and b are added as two integers (and an overflow occurs) then to the result of that c (a long) is added. When calculating s2 first c and b are added (as long) and then a is added (promoted as long) thus no overflow occurs.
答案指出算术提升。但考虑到这一点,我陷入了以下陷阱(我很惭愧),我想在这里指出:如果对我来说有两个以上的操作数,似乎计算是从左到右执行的,如果实际有两个,则会发生算术提升焦点中的操作数具有不同的类型。因此,以下代码对 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);
The output will be:
s1=-2147483647, s2=2147483649
输出将是:
s1=-2147483647, s2=2147483649