I have seen this question asked before. However, I am not satisfied with the answers that are given. Typical responses are that Java sees the number as a double, since that is the default in JAVA, and gives a mismatch error on compiling.
This behavior is apparently totally ignoring my use of a float declaration.
My question is: If I am declaring a variable type as float
, why does Java think it is a double? I am specifically declaring:
float x = 3.14;
I have told Java that I want this variable to be a float type by using the float keyword. Why is this required?
float x = 3.14f;
If I want a double type variable, I use the double keyword specifically declaring the variable as a double.
double x = 3.14;
Why does Java not recognize this when declaring a variable and insists the literal needs to be cast from a double to a float by adding the 'f' at the end? Shouldn't Java recognize the use of the keyword float
and properly assign the type to the literal?
32-bit float → float x = 3.14 ;
← 64-bit double
The default for a fractional numeric literal in Java is the 64-bit primitive double
type, as shown in the Answer by Mark Rotteveel. 3.14
is a double
, as is 3.14d
and 3.14D
.
The primitive float
type is smaller, 32-bit.
If Java were to infer that what you said is a double
but what you meant is a float
, Java would have to reduce the 64-bit value to a 32-bit value, discarding half the data, 32-bits. This could involve data loss for larger numbers. And this would definitely mean a loss of capacity.
So the designers of Java decided to be conservative in this matter. They decided to not be so presumptive as to throw away half your data, nor to reduce your specified capacity by half. They decided to take you at your word — if you said 64-bit double
, they give you a double
.
If you then go on to say you want to cram that 64-bit number into a 32-bit container, they flag the error, as 64-bits does not fit into 32-bits. Square peg, round hole.
round hole, 32-bit float → float x = 3.14 ;
← 64-bit double, square peg
Java does support the converse, a widening conversion. You can put a 32-bit float
into a 64-bit double
. And you can put a 32-bit int
into a 64-bit long
. These operations are safe, as the extra 32-bits can be filled safely with zeros. So Java is willing and able to support these operations.
I suggest you make a habit of being explicit. Do not rely on the default. If you mean a 32-bit float
, append the f
or F
to your literal. If you mean a 64-bit double
, append the d
or D
to your literal.
Doing so not only quiets the compiler, it makes your intentions clear to the humans reading your code.
float pi = 3.14F ;
double pi = 3.14d ;
BigDecimal
And, by the way, if you care about accuracy rather than performance, you’ll be using BigDecimal
rather than float
/double
. In which case this issue is moot.
BigDecimal pi = new BigDecimal( "3.14" ) ;
The reason is that the Java Language Specification specifies that a floating point literal without the f
or F
suffix, is a double
. From Floating-Point Literals in the Java 15 Language Specification:
A floating-point literal is of type
float
if it is suffixed with an ASCII letterF
orf
; otherwise its type isdouble
and it can optionally be suffixed with an ASCII letterD
ord
.
Java doesn't try to infer the type of the literal based on the type of the variable you're assigning to. A double-literal is simply always a double
. In other words, semantically, it behaves the same as if your code did:
double temp = 3.14;
float x = temp;
Which will also fail to compile, because assigning a double
to a float
can result in loss of information, if the magnitude of the value is too large to fit in a float
. This is known as narrowing primitive conversion, and requires an explicit cast to tell the compiler you're aware of the risk and you accept it.
In some cases, it may seem as if Java will perform inference of type from the variable (e.g. when assigning an int
or long
literal to a double
or float
variable), but that is because the entire range of int
and long
can be stored in a float
or double
(possibly with loss of precision). This is known as widening primitive conversion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With