byte b=42: good, float f=4.2: bad

A

Andreas Leitgeb

Integer literals are per default of type "int", fine.
Floating point literals are per default type "double", fine.

For initializers, integer arguments are automatically cast down:
byte b=42;
Why not for floats?
float f=4.2; --> error: possible loss of precision.

Of course I know, that I can add an "f", to solve this, but why?
Why doesn't javac follow the same reasons as for the integral case?
 
?

=?ISO-8859-15?Q?Tobias_Schr=F6er?=

Hi,

Andreas said:
Integer literals are per default of type "int", fine.
Floating point literals are per default type "double", fine.

For initializers, integer arguments are automatically cast down:
byte b=42;
Why not for floats?
float f=4.2; --> error: possible loss of precision.

Of course I know, that I can add an "f", to solve this, but why?
Why doesn't javac follow the same reasons as for the integral case?

the message tells you why ;)

If you convert the int value of 42 to an byte value, its still exactly
42. Bytes and integers are natural numbers.

If you convert the double value of 4.2 to a float, you might loose
precision. If you look at the bit representation of a float and a
double, the double value is more precise (double precision). Double and
float are only approximations to numbers.
To overstate: the double value is 4.2000000000 and the float value could
be 4.199999999 due to the missing precision. The actual differences
would be much smaller, I think. That simply because there might be no
float representation that "exactly" hits 4.2, whereas a double
representation does.

Google for some reading on that topic, if you like. You should fing loads.

Regards,
Tobi
 
A

Andreas Leitgeb

If you convert the int value of 42 to an byte value, its still exactly
42. Bytes and integers are natural numbers.

note further, that
byte b;
b=42;
does, however, fail with the "possible loss of precision" message.

So, if javac was intelligent enough to recognize the constant 42
as fitting into a byte, it could also see it fits into a byte
at a later time.

It is not that intelligent, but it suppresses the error
specifically for initialization.

My question was: why doesn't it also suppress the warning
for floats as well, and implicitly assume a trailing "f"
if it is clear that the literal is exclusively used to
initialize a float-typed variable.
If you convert the double value of 4.2 to a float, you might loose
precision.
Of course, 4.2 was not an ideal example, but the result isn't
different, if we use 42. or 42.5 which are *exactly*
represened in any base-2 floating point math. both float and double
can carry 42.5 lossless.
Google for some reading on that topic, if you like. You should fing loads.
I failed to come up with concise keywords for this problem.
googling on: java float initializer gives me gobs of unrelated
hits.
 
?

=?ISO-8859-1?Q?Tobias_Schr=F6er?=

Andreas said:
Tobias Schröer said:
Andreas Leitgeb schrieb:
[..]
Google for some reading on that topic, if you like. You should fing loads.

I failed to come up with concise keywords for this problem.
googling on: java float initializer gives me gobs of unrelated
hits.
Try 'java "loss of precision"'. I only had a brief reading but there
seemed to be some useful things. Have you searched the java specs?
 
A

Andreas Leitgeb

Tobias Schröer said:
Try 'java "loss of precision"'. I only had a brief reading but there
seemed to be some useful things. Have you searched the java specs?

That gave me more relevant hits, thanks, but still these hits
only state how it is, and I knew that (I mentioned with my first
question, that I knew I could fix it by appending an "f")

My question was less of type:
"how can it be done",
but instead:
"Why was it specified such?"

And my question was also specifically addressing the
context of inititializers, where for byte,char,short
the compiler is obviously less picky/fussy/....
 
P

Patricia Shanahan

Andreas said:
That gave me more relevant hits, thanks, but still these hits
only state how it is, and I knew that (I mentioned with my first
question, that I knew I could fix it by appending an "f")

My question was less of type:
"how can it be done",
but instead:
"Why was it specified such?"

And my question was also specifically addressing the
context of inititializers, where for byte,char,short
the compiler is obviously less picky/fussy/....

I think there are two differences to consider:

1. For e.g. byte, if the constant is within the variable's range, it is
exactly convertible. Some doubles within the float range can be
converted exactly to float, others cannot.

Moreover, casting a double literal to float does not always give the
same answer as the corresponding float literal - rounding twice can
confuse matters.

2. Probably to avoid forcing rounding twice, the language provides a
distinct, no-cast, syntax for float literals, the use of a trailing "F"
or "f". That is what should be used for maximum accuracy:

float f = 4.2F;

not

float f = (float)4.2;

which would be the analog to:

byte b = (byte)42;

Patricia
 
A

Andreas Leitgeb

Patricia Shanahan said:
2. Probably to avoid forcing rounding twice, the language provides a
distinct, no-cast, syntax for float literals,

hmm, meanwhile it makes sense: casting from int down to
a smaller type is actually a noop, whereas casting from
double to float is indeed a "calculation"...

Thanks, I think I got it now.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top