final long b = 123123;
final long c = 123123*123123*123123;
long d = b*b*b;
System.out.println(c);
System.out.println(d);
output :
-162426261
1866455185461867
In the case of the first printout, it seems that overflow occurs because Java treats it as an integer rather than a long one, but why is it not calculated as an integer in the second case? I thought that if I put final in front of long and make it a constant, it would be calculated in compile time, so I thought that the second and first output sentences should have the same result, but I want to know why I was wrong.
Because numeric literals without a decimal point in Java treated as int, variable c gets initialized with an overflown result of int multiplication.
Conversely, variable d is assigned to a result of multiplication that is done on long values (because b is of type long).
Basically you have:
long c = int * int * int; // multiply `int` numbers and then promote an overflown result into `long`
long d = long * long * long;
I thought that if I put final in front of long and make it a constant, it would be calculated in compile time
Variables b and c are compile-time constants, because they are primitive, marked as final, assigned at the moment of declaration and initialized with constant expressions. All accuracies of these variables in the code would be replaced with their values. But it doesn't change how the value of c is calculated.
Variable d isn't a compile-time constant because it has no final modifier. But this fact also has no effect on the way how its value is calculated.
Since your value of c won't contain decimal points, it will be treated as an int. To solve this just add "L"(L stands for long)
final long c = 123123L*123123L*123123L;
public class MyClass {
public static void main(String args[]) {
final long b = 123123;
final long c = 123123L*123123L*123123L;
long d = b*b*b;
System.out.println(c);
System.out.println(d);
}
}
Output
1866455185461867
1866455185461867
Related
This question already has answers here:
Using the letter L in long variable declaration
(2 answers)
Closed 5 years ago.
What's the difference between the following?
long var1 = 2147483647L;
long var2 = 2147483648;
(or any primitive variable declaration)
Does it have any performance issue with or without L? Is it mandatory?
In the first case you are assigning a long literal to a long variable (the L or l suffix indicates long type).
In the second case you are assigning an int literal (that's the default type when no suffix is supplied) to a long variable (which causes an automatic type cast from int to long), which means you are restricted to the range from Integer.MIN_VALUE to Integer.MAX_VALUE (-2147483648 to 2147483647).
That's the reason why
long var2 = 2147483648;
doesn't pass compilation (2147483648 is larger than Integer.MAX_VALUE).
On the other hand
long var2 = 2147483648L;
would pass compilation.
For easy understanding each of the type have range in java.
By default every digit you entered in java is either byte or short or integer.
short s = 32767;
byte b = 127;
int i = 2147483647;
So if you assign anything except from their range you'll get compilation error.
int i = 2147483648; //compilation error.
Type range
And when you write long longNumber = 2147483647;
though it falls in long range but internally java treat it as
long l = (int) 2147483647;
you wont get any errors.
But if we assign beyond the range of integer like
longNumber = 2147483648; we will get compilation error as
long o = (int) 2147483648;
here java will try to convert the 2147483648 to int but it is not in int range so widening error is thrown.
To indicate java that the number what we have written is beyond the integer range just append l or L to the end of the number.
so java will wide his range till long and convert it as
long o = (long) 2147483648;
By default every floating point or digit with floating points (.) are size of double. So when you write some digits with (.) java treat as a double and it must be in double range.
As we know the float range is smaller then double.
so when you write
float f = 3.14;
though it falls in double range but internally java treat this assignment as
float f = (double) 3.14;
here you are assigning the double to float narrowing which is not correct.
so either you have to convert the expression like that
float f = (float)3.14;
or
float f = 3.14f; // tell jvm to assign this in float range by appending **f** or **F**
If we don't mention the L with the value then value is considered to be int value.
It type casts the int to long automatically.
Why does this output 0 instead of 1?
System.out.println((int) (Math.ceil(1/2)));
While this one correct outputs 1
System.out.println((int) (Math.ceil((double) 1/ (double) 2)));
Shouldn't Math.ceil(double) automatically type cast the 1/2 to double?
Math.ceil does, indeed, cast the integer to a double. But it only does so after the integer operation has been performed. This is the order of operations:
int a = 1;
int b = 2;
int c = a / b; // now equals 0, because it's an integer operation.
double d = (double)c; // now it's a double - but equals 0.0.
double e = Math.ceil(d); // still 0.0.
You're thinking of 1/2 as a fraction, but it's not - it's an expression of two ints and an operator that has to be resolved before its value can be used in further expressions.
Explicit casting always require (datatype) to be mentioned. Here 1 and 2 represents itself as int and to cast from int to double explicit casting will be introduced. Whenever casting is preformed from lower to higher datatypes explicit casting should be imposed. See example below;
public class MainClass{
public static void main(String[] argv){
int a = 100;
long b = a; // Implicit cast, an int value always fits in a long
}
}
An explicit casts looks like this:
public class MainClass{
public static void main(String[] argv){
float a = 100.001f;
int b = (int)a; // Explicit cast, the float could lose info
}
}
Code Snippet: Source
The first thing which happens when that line is executed, is that the division 1/2 is resolved. This happens without any consideration for the method-call to Math.ceil it is embedded in.
The literals 1 and 2 are integers. When you perform a division with only integers as arguments, an integer division is performed, which always rounds down. So the term gets resolved to the int value 0. Math.ceil() only accepts type double, but that's not a problem because Java can perform the conversion automatically and turn the int 0 to a double 0.0.
To perform an explicit floating point division, have one or both of the parameters to the division be floating point literals:
System.out.println((int) (Math.ceil(1.0/2.0)));
I have the methods overloading such as:
public int sum1(int a, int b)
{
int c= a+b;
System.out.println("The method1");
return c;
}
public float sum1(int a, float b)
{
float c= a+b;
System.out.println("The method2");
return c;
}
public double sum1(float a, float b)
{
double c= (double) a+b;
System.out.println("The method3");
return c;
}
From the main method, suppose we have
double x=10.10f;
double y=10.20f;
the apparent type for x and y is double, but the actual type is float. when I call
System.out.println(" the output is :"+cc.sum1(x,y));
the error in the compile-time.
The method sum1(int, int) in the type Class is not applicable for the arguments double, double).
where it should go to sum1 (i.e. method3) by casting double to float
TL;DR version of this answer:
Variables of primitive types never have a different type at execution-time to their compile-time. (A double is always a double, never a float, etc.)
Overload resolution (picking which method signature is used) is performed using the compile-time types of expressions
Method implementation of the picked signature is performed using the execution-time type of the target of the method call
the apparent type for x and y is double, but the actual type is float
No, it's not. You've just got a conversion from the assigned float literals to double values. The actual values are double.
Primitives don't work like objects - there's no idea of an int value still being an int inside a double variable, for example.
It's simpler to take an example with integer types. Suppose we have:
byte b = 100;
int x = b;
The value of x is the 32-bit integer representing the value 100. It doesn't "know" that it was originally assigned from a byte value... there just happened to be a conversion from byte to int at the point of assignment.
Compare that with reference types:
String x = "hello";
Object y = x;
Here, the value of y really is a reference to a String object. That type information is preserved precisely because there's a whole object that can contain it, and because the value of the variable itself is only a reference. (The bits themselves don't need to change as part of the assignment - in a simple VM at least, they'll be the exact same bits in x and y, because they're referring to the same object.)
Even in that case, however, overload resolution occurs based on the compile-time type of the arguments, not their actual values at execution time. The only way that the execution-time type of a variable gets involved is with overriding based on the target of a method call. So if we have:
Foo f = new X();
Foo g = new Y();
Foo h = new Z();
f.someMethod(g, h);
... then the compiler will look for a method in Foo which has two Foo parameters (or Object or other superclasses/interfaces) - the actual types of the objects involved are irrelevant. At execution time, however, if that method has been overridden in X, then that override will be called due to the execution-time type of the object f's value refers to.
Casting double to float may cause loss of data, since it's a narrowing conversion, and is therefore not done automatically by the compiler. You'll have to cast the variables to float explicitly if you want it to take place.
No, the actual type of the variables is double. The type of the constants that you're assigning to that double variable, which get promoted on assignment, is float.
Try to add new function: public double sum1(double a, double b). It will solve your problem.
And also, this kind of casting will cause loss of data.
Floats are funny that way.. they always try to convert to doubles automatically. This code compiles, with floats at every turn.
public class wood {
public static void main(String[] args) {
float x = 10.1f;
float y = 10.2f;
System.out.println("Sum of x and y = " + sum1((float)x, (float)y));
}
public static float sum1(float x, float y) {
return (float)((float)x+(float)y);
}
}
edit; note that using a cast operator outside of parenthesis will cast after what is inside of the parenthesis has computed. So;
System.out.println((int)(50.5 + 50.7));
will print out 101.
Within java, some data conversions are automatic, and others require cast operators.. simply put, java will automatically make widening conversions, while you will have to use a cast operator for narrowing conversions.
The hierarchy of primitive data types is as follows:
byte //1 byte (-128 through 127)
short //2 bytes (over 32,000 give/take from 0)
int //4 bytes (over 2billion give/take from 0)
long //8 bytes (over 9 quintillion (10^18) give/take from 0)
float //4 bytes (holds 7 decimal places)
double //8 bytes (holds 15 decimal places)
java will not make narrowing conversions automatically, because then data is at risk of being lost. Both byte and short will become ints automatically.
short s = 5;
byte b = 5;
short sum = s + b; //this will cause an error!
s and b automatically make a widening conversion to an int, and an int cannot be assigned to a short without a cast operator.
short sum = (short)(s + b);
would be needed.
I have a code in which I need to divide an integer by a very big number e.g. 12345678912. I used long but it still gives error as The literal 12345678912 of type int is out of range.
Code for example:
public static void main(String[] args) {
//rest of the code
long x = 12345678912; //<--error is in this statement
System.out.println(y/x); //<---y is an integer which is having some value in rest of the code.
}
I know that the maximum value that an unsigned long can hold is 2^(64)-1. But then, I want to know, how to achieve this in Java? Is there any way to achieve it directly, or I need to implement any algorithm?
Java Language Specification
An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (ยง4.2.1).
You need to tell that the data type is long by appending literal l or L
long x = 12345678912L;
Examples work best, imagine Object is a Byte and we attempt to cast it to a long...
Currently the byte code looks a bit like this
Byte b = Byte.valueOf(1);
Object source = b;
Long long = (Long) source; // fails CCE because a Byte is not a Long
long value = long.longValue();
Wouldnt a cast to Number be better ?
Byte b = Byte.valueOf(1);
Number number = (Number) b; // f
long value = number.longValue();
The real problem is of course we have reduce the possibility for ClassCastExceptions, is that a bad thing ?
Why cast at all? Bytes have the longValue() method as well.
Byte b = Byte.valueOf(1);
long value = b.longValue();
Or better yet:
byte b = 1;
long value = (long) b;
If you don't care what the original type is, I would just cast to a Number as you have done.
From smaller ints to bigger ones, you don't need casting. It is called promotion and works by assignment:
byte b = (byte) 200;
long l = b;
Long ll = l;
For Byte-byte and long-Long conversion you can use autoboxing.