So at the top of my code I declared the variable
private long counter;
And when I try to give it a number that's really long it gives an error, Im trying to do this
counter = 1111111111111111;
Thats 16 "1"s and I keep getting the error "The literal 1111111111111111 of type int is out of range" what am I doing wrong?
Try it like this:
counter = 1111111111111111l;
Note that the last character there is the letter 'L' (lowercase, of course), and not the number one. Here is a clearer example:
counter = 2222222222222222L;
As others have pointed out, an uppercase 'L' also works and is much more clear. All integer literals in Java are interpreted as ints unless you suffix them with an 'L' (or 'l') to tell the compiler to interpret it as a long.
A similar thing happens with literal floating-point numbers, which are interpreted as doubles by default unless you suffix them with an 'f' to tell the compiler to interpret it as a float. As in:
double num1 = 1.0; //1.0 is treated as a literal double
float num2 = 1.0; //1.0 is still treated as a literal double; the compiler may complain about loss of precision
float num3 = 1.0f; //1.0 is treated as a float, and the compiler is happy
The java compiler reads any number as an integer by default. 11111111111 is obviously outside the range of an integer. Type counter=11111111111L; to get the compiler to read the value correctly.
The problem is that numeric literals are ints by default. To make the numeric literal a long you have to finish it with the alpha character l (lower-case L). So:
long counter = 1111111111111111l;
In C# you can also use an upper-case L. I'm not sure about Java.
Related
I am working with data types at the moment in Java, and if I have understood correctly the type long accepts a value between the ranges of -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807. Now as you can see below, I have create a long variable called testLong, although when I insert 9223372036854775807 as the value, I get an error stating:
The literal 9223372036854775807 of the type int is out of range.
I don't know why it is referring to the long data type as an int.
Anyone have any ideas?
Code:
char testChar = 01;
byte testByte = -128;
int testInt = -2147483648;
short testShort = -32768;
long testLong = 9223372036854775807;
float testFoat;
double testDouble = 4.940656458412;
boolean testBool = true;
Add a capital L to the end:
long value = 9223372036854775807L;
Otherwise, the compiler will try to parse the literal as an int, hence the error message
I don't know why it is referring to the long data type as an int
It is not. You should learn to trust compiler messages (especially when they are from sane, modern compilers and not ancient compilers that tended to have bad error messages). While the language that they speak might be hard to decipher at times, they are not usually lying to you.
Let's look at it again:
The literal of int 9223372036854775807 is out of range.
Note, that it doesn't mention your variable testLong or the type long anywhere, so the problem is not about the initialization. It seems to occur at some other point.
Now lets investigate some of the parts of the message:
int tells us that he wants to treat something as an int value (which is not what you wanted!)
"out of range" is pretty clear: something is not within the expected range (probably that of int)
"The literal": now that's interesting: what is a literal?
I'll leave the cozy list to talk about literals for a moment: literals are places where you have some value in your code. There are String literals, int literals, class literals and so on. Every time you mention a value explicitly in your code, it's a literal.
So it's not actually nagging you about the variable declaration, but the number itself, the value is what it's nagging you about.
You can easily verify this by using the same literal in a context where a long and an int are equally acceptable:
System.out.println(9223372036854775807);
PrintStream.println can take either an int or a long (or pretty much anything else). So that code should be fine, right?
No. Well, maybe it should be, but according to the rules it is not fine.
The problem is that "some digits" is defined to be an int literal and therefore must be in the range defined by int.
If you want to write a long literal, then you must make that explicit by appending the L (or lower case l, but I highly suggest you always use the upper-case variant, because it's much easier to read and harder to mistake for a 1).
Note that a similar problem occurs with float (postfix F/f) and double (postfix D/d).
Side note: you'll realize that there are no byte or short literals and you can still assign values (usually int literals) to byte and short variables: that's possible due to special rules in § 5.2 about conversions in an Assignment Contexts: they allow assignment of constant expressions of a larger type to byte, short, char or int if the values are within the types range.
Try doing 9223372036854775807L. The L at the end tells Java that 9223372036854775807 is a long.
I had this problem in the past and I fixed that by writing the value in the scientific form.
for example:
double val = 9e300;
long ak = 34778754226788444L/l;
Both use but at a time only one use uppercase L or lowercase l.
Why use L/l? Because long is a part of integral datatype.
I am working with data types at the moment in Java, and if I have understood correctly the type long accepts a value between the ranges of -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807. Now as you can see below, I have create a long variable called testLong, although when I insert 9223372036854775807 as the value, I get an error stating:
The literal 9223372036854775807 of the type int is out of range.
I don't know why it is referring to the long data type as an int.
Anyone have any ideas?
Code:
char testChar = 01;
byte testByte = -128;
int testInt = -2147483648;
short testShort = -32768;
long testLong = 9223372036854775807;
float testFoat;
double testDouble = 4.940656458412;
boolean testBool = true;
Add a capital L to the end:
long value = 9223372036854775807L;
Otherwise, the compiler will try to parse the literal as an int, hence the error message
I don't know why it is referring to the long data type as an int
It is not. You should learn to trust compiler messages (especially when they are from sane, modern compilers and not ancient compilers that tended to have bad error messages). While the language that they speak might be hard to decipher at times, they are not usually lying to you.
Let's look at it again:
The literal of int 9223372036854775807 is out of range.
Note, that it doesn't mention your variable testLong or the type long anywhere, so the problem is not about the initialization. It seems to occur at some other point.
Now lets investigate some of the parts of the message:
int tells us that he wants to treat something as an int value (which is not what you wanted!)
"out of range" is pretty clear: something is not within the expected range (probably that of int)
"The literal": now that's interesting: what is a literal?
I'll leave the cozy list to talk about literals for a moment: literals are places where you have some value in your code. There are String literals, int literals, class literals and so on. Every time you mention a value explicitly in your code, it's a literal.
So it's not actually nagging you about the variable declaration, but the number itself, the value is what it's nagging you about.
You can easily verify this by using the same literal in a context where a long and an int are equally acceptable:
System.out.println(9223372036854775807);
PrintStream.println can take either an int or a long (or pretty much anything else). So that code should be fine, right?
No. Well, maybe it should be, but according to the rules it is not fine.
The problem is that "some digits" is defined to be an int literal and therefore must be in the range defined by int.
If you want to write a long literal, then you must make that explicit by appending the L (or lower case l, but I highly suggest you always use the upper-case variant, because it's much easier to read and harder to mistake for a 1).
Note that a similar problem occurs with float (postfix F/f) and double (postfix D/d).
Side note: you'll realize that there are no byte or short literals and you can still assign values (usually int literals) to byte and short variables: that's possible due to special rules in § 5.2 about conversions in an Assignment Contexts: they allow assignment of constant expressions of a larger type to byte, short, char or int if the values are within the types range.
Try doing 9223372036854775807L. The L at the end tells Java that 9223372036854775807 is a long.
I had this problem in the past and I fixed that by writing the value in the scientific form.
for example:
double val = 9e300;
long ak = 34778754226788444L/l;
Both use but at a time only one use uppercase L or lowercase l.
Why use L/l? Because long is a part of integral datatype.
This question already has answers here:
Reasoning behind having to specify L for long, F,D for float, double
(3 answers)
Closed 8 years ago.
When I execute this code in java:
long l = 999_999_999_999;
I get the following error,
error: integer number too large: 999999999999
long l = 999_999_999_999;
But if I explicitly specify the number as long by adding l or L at the end, the problem disappears.
long l = 999_999_999_999L; // Works
My question is, why?
I know that all integral literals in java are integer by default, but why it would stop java from type casting and accommodating the value in a long, when a long is clearly large enough to hold the literal?
I am looking for some technical details.
This is perfectly intended.
Think about how the program is parsed. The lexer which splits the Java source into tokens knows about two things of literal:
the ones which don't end with [L|l]
the ones which end with [L|l]
A literal which doesn't have the long specifier at the end is parsed as an integer. This means that the literal itself is invalid because you are not allowed to define an integer literal which is larger than the larger number that you can represent with an int.
This is clear in the grammar specification here:
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).
It is a compile-time error if a decimal literal of type int is larger than 2147483648 (231), or if the decimal literal 2147483648 appears anywhere other than as the operand of the unary minus operator (§15.15.4).
So even without any assignment, if you have the expression
999_999_999_999
This is parsed as an integer literal, but its value is over the maximum allowed value, hence it is illegal. The fact that the value of this expression is later assigned to something is irrelevant.
Java won't automatically cast your int literal as a long, because the int literal is invalid in the first place. That's why long literals exist, so values greater in magnitude can be expressed as literals.
According to the JLS, Section 3.10.1:
It is a compile-time error if a decimal literal of type int is larger than 2147483648 (231), or if the decimal literal 2147483648 appears anywhere other than as the operand of the unary minus operator (§15.15.4).
In Java, you simply can't have an int literal bigger than Integer.MAX_VALUE, even if its only use is to assign a value to a long. Bigger literals must be long with an L suffix to begin with.
If your going to understand your problem. You will have to understand how Java reads and assign values to variables.
Java first reads the value that you want to assign to the variable, which is "99999999" then assigns it to the variable.
Without the "L" at the end, Java reads the value of the number, but encounters the problem that it is too big for an int. with the "L" at the end, Java knows it is a Long, therefore it is large enough.
I have read a section about literals and how they are used. For example you would add l or L at the end of a number to denote that the int is a long type. Same goes with the floating point numbers (f or F and d or D). What is the point of distinguishing this character at the end of a number. When we give the type does it not already know why specify again? So, what exactly is the point of adding this character to the end of a number? Where is it being used?
I have tried searching these questions on google and stack overflow already, but have not been able to receive a well developed answer to it.
The compiler knows how to treat the final result of an expression, but the individual literals (or variables) in an expression each have their own types, as do the intermediate values in the expression. For example:
static final double HALF = 1 / 2;
will actually have the value zero, because the literal 1 and 2 are int-typed, the division is an integer division that produces an int value of zero, and then Java turns that into a double. In contrast, in the expression
static final double HALF = 1d / 2;
the compiler knows to treat the first value as a double. The second value is promoted, Java does floating-point division, and the result is 0.5 as expected.
There are other situations, like autoboxing, where the compiler may treat equivalent values differently depending on their types; when passed to a method that takes an Object, 0 is an Integer, while 0L is a Long. This sort of situation occurs frequently in persistence/DAO code. Also, when compiling, the compiler evaluates compile-time constant expressions and puts their values directly into the code. The values of float and double expressions may be different because of the differing precisions of the types, and so you need to specify if you want a floating-point expression treated as just a float instead of as a double (the default).
You can not use a value greater than 2147483647 anywhere in java unless you have appended L or D to it. l makes the literal long type and d makes the literal double type.
e.g. System.out.println(2147483648); will result in an error as well as
long num=2147483650; will also result in an error as these literals are no longer int type which the default type for the integers. So by appending l or d to a number you can use it as int or double type.
I understand that "2.5" is automatically a double, and to make it a float, I need to do "2.5F" (or should the F be lowercase?), and that I should use a float, say, if I had a constant that only ever needed 2 decimal spaces (like "0.08F" for Ontario PST tax), but I'm not sure whether "12" is an int or a long, but I know "12L" is a long, but "long l = 12" and "long l = 12L" seem to compile to the same thing, and I use long's if I want maximum non-floating point precision, and int if I know I won't need beyond int's limits.
Please correct me if there's something there that isn't right, and answer the quesions I have.
12 as a constant in java is an int.
The reason long l = 12 compiles is that it is automatically widened to a long.
EDIT: Regarding your comment, there is nothing wrong with automatic widening, use whatever makes your code clearer, but just be aware of what is going on when you do math on primitives. For example:
int i = 1213;
long l = 112321321L * i;
The long will have a very different value if you don't explicitly put that first number as a long because Java will treat it as integer math, and cause an overflow.
It doesn't make a difference if you use lower or upper case when declaring your floats .
...like "0.08F" for Ontario PST tax
If you are using these fields for currency, you should consider using BigDecimal instead. See this explanation and its related links from Sun for more detail.
First, 12 is an int. Since you didn't specify a type, the compiler assumes int, just as it assumes double when you don't specify a type for 2.5.
The assignment
long x = 12;
compiles just fine because there is no loss of precision when the compiler implicitly upcasts the literal int value 12 to a long.
I always try to use uppercase type specifiers like 2.5F and 12L, simply because they're easier to read. 1 and l look much the same in the monospaced font that I prefer.
Note that while int literals will be auto-widened to long when assigning to a long variable, you will need to use an explicit long literal when expressing a value that is greater than Integer.MAX_VALUE (2147483647) or less than Integer.MIN_VALUE (-2147483648):
long x1 = 12; //OK
long x2 = 2147483648; // not OK! That's not a valid int literal
long x3 = 2147483648L; // OK