Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Possible loss of precision

Reply
Thread Tools

Possible loss of precision

 
 
Stefan Ram
Guest
Posts: n/a
 
      11-13-2013
When one writes

char x = 'C' + 1;
x = x + 1;

in a block, one gets an error message

»possible loss of precision«

for »x = x + 1«. Ok, fair enough: »x + 1« has type »int«,
and precision is lost when assigning this to the variable x
of type char.

I was somewhat surprised, though, that »char x = 'C' + 1;«
does not yield an error, even though the type of »'C' + 1«
is int, too. Possibly, this time, the compiler can figure
out that the actual value still fits into a char.

But then, »int i = 2.0;« gives an error, even though the
compiler should see that »2.0« can be represented as an int.

 
Reply With Quote
 
 
 
 
Michael Jung
Guest
Posts: n/a
 
      11-14-2013
http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de (Stefan Ram) writes:
> char x = 'C' + 1;
> x = x + 1;
> in a block, one gets an error message
> »possible loss of precision«
> for »x = x + 1«. Ok, fair enough: »x + 1« has type »int«,
> and precision is lost when assigning this to the variable x
> of type char.
> I was somewhat surprised, though, that »char x = 'C' + 1;«
> does not yield an error, even though the type of »'C' + 1«
> is int, too. Possibly, this time, the compiler can figure
> out that the actual value still fits into a char.
> But then, »int i = 2.0;« gives an error, even though the
> compiler should see that »2.0« can be represented as an int.


You are right that x+1 is "promoted" to int and the second assignment
fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
This concerns constant expressions first and the second allows a
narrowing in rare cases, of which the first line is one but the
"int i = 2.0" isn't.
 
Reply With Quote
 
 
 
 
Gene Wirchenko
Guest
Posts: n/a
 
      11-14-2013
On Thu, 14 Nov 2013 20:39:42 +0100, Michael Jung
<(E-Mail Removed)> wrote:

>(E-Mail Removed)-berlin.de (Stefan Ram) writes:
>> char x = 'C' + 1;
>> x = x + 1;
>> in a block, one gets an error message
>> »possible loss of precision«
>> for »x = x + 1«. Ok, fair enough: »x + 1« has type »int«,
>> and precision is lost when assigning this to the variable x
>> of type char.
>> I was somewhat surprised, though, that »char x = 'C' + 1;«
>> does not yield an error, even though the type of »'C' + 1«
>> is int, too. Possibly, this time, the compiler can figure
>> out that the actual value still fits into a char.
>> But then, »int i = 2.0;« gives an error, even though the
>> compiler should see that »2.0« can be represented as an int.

>
>You are right that x+1 is "promoted" to int and the second assignment
>fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
>This concerns constant expressions first and the second allows a
>narrowing in rare cases, of which the first line is one but the
>"int i = 2.0" isn't.


Why isn't it though?

Sincerely,

Gene Wirchenko
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      11-14-2013
On 11/14/2013 6:03 PM, Gene Wirchenko wrote:
> On Thu, 14 Nov 2013 20:39:42 +0100, Michael Jung
> <(E-Mail Removed)> wrote:
>
>> (E-Mail Removed)-berlin.de (Stefan Ram) writes:
>>> char x = 'C' + 1;
>>> x = x + 1;
>>> in a block, one gets an error message
>>> »possible loss of precision«
>>> for »x = x + 1«. Ok, fair enough: »x + 1« has type »int«,
>>> and precision is lost when assigning this to the variable x
>>> of type char.
>>> I was somewhat surprised, though, that »char x = 'C' + 1;«
>>> does not yield an error, even though the type of »'C' + 1«
>>> is int, too. Possibly, this time, the compiler can figure
>>> out that the actual value still fits into a char.
>>> But then, »int i = 2.0;« gives an error, even though the
>>> compiler should see that »2.0« can be represented as an int.

>>
>> You are right that x+1 is "promoted" to int and the second assignment
>> fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
>> This concerns constant expressions first and the second allows a
>> narrowing in rare cases, of which the first line is one but the
>> "int i = 2.0" isn't.

>
> Why isn't it though?


Speculation: The fact that a floating-point expression happens
to evaluate to a number with no fractional part doesn't mean the
value "is" an integer. One reasonable view of FP is that a value
is just a representative of a range of real values, namely, all
those real values that round to the representative. In this
view, converting 2.0 to 2 *does* lose precision, specifically,
the amount of wiggle room.

Then again, maybe the Java designers were just FP-wary.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)d
 
Reply With Quote
 
Joerg Meier
Guest
Posts: n/a
 
      11-14-2013
On Thu, 14 Nov 2013 18:31:53 -0500, Eric Sosman wrote:

> On 11/14/2013 6:03 PM, Gene Wirchenko wrote:
>> On Thu, 14 Nov 2013 20:39:42 +0100, Michael Jung
>> <(E-Mail Removed)> wrote:
>>> You are right that x+1 is "promoted" to int and the second assignment
>>> fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
>>> This concerns constant expressions first and the second allows a
>>> narrowing in rare cases, of which the first line is one but the
>>> "int i = 2.0" isn't.

>> Why isn't it though?

> Speculation: The fact that a floating-point expression happens
> to evaluate to a number with no fractional part doesn't mean the
> value "is" an integer. One reasonable view of FP is that a value
> is just a representative of a range of real values, namely, all
> those real values that round to the representative. In this
> view, converting 2.0 to 2 *does* lose precision, specifically,
> the amount of wiggle room.


My instinctive mental reply was that 2.0 instead of 2 is an explicit
instruction to use double, much like L or F, which you wouldn't want to be
silently ignored.

Liebe Gruesse,
Joerg

--
Ich lese meine Emails nicht, replies to Email bleiben also leider
ungelesen.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      11-15-2013
On 11/14/2013 6:31 PM, Eric Sosman wrote:
> On 11/14/2013 6:03 PM, Gene Wirchenko wrote:
>> On Thu, 14 Nov 2013 20:39:42 +0100, Michael Jung
>> <(E-Mail Removed)> wrote:
>>
>>> (E-Mail Removed)-berlin.de (Stefan Ram) writes:
>>>> char x = 'C' + 1;
>>>> x = x + 1;
>>>> in a block, one gets an error message
>>>> »possible loss of precision«
>>>> for »x = x + 1«. Ok, fair enough: »x + 1« has type »int«,
>>>> and precision is lost when assigning this to the variable x
>>>> of type char.
>>>> I was somewhat surprised, though, that »char x = 'C' + 1;«
>>>> does not yield an error, even though the type of »'C' + 1«
>>>> is int, too. Possibly, this time, the compiler can figure
>>>> out that the actual value still fits into a char.
>>>> But then, »int i = 2.0;« gives an error, even though the
>>>> compiler should see that »2.0« can be represented as an int.
>>>
>>> You are right that x+1 is "promoted" to int and the second assignment
>>> fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
>>> This concerns constant expressions first and the second allows a
>>> narrowing in rare cases, of which the first line is one but the
>>> "int i = 2.0" isn't.

>>
>> Why isn't it though?

>
> Speculation: The fact that a floating-point expression happens
> to evaluate to a number with no fractional part doesn't mean the
> value "is" an integer. One reasonable view of FP is that a value
> is just a representative of a range of real values, namely, all
> those real values that round to the representative. In this
> view, converting 2.0 to 2 *does* lose precision, specifically,
> the amount of wiggle room.


As a more concrete example,

static final double FOO = 17.316;
static final double BAR = 8.658;
int i = FOO / BAR; // Should javac be silent here?

Neither the numerator nor the denominator can be represented
exactly as stated, yet the quotient is (probably; cook up your
own numbers if mine are faulty) exactly 2.0. Would it be a
good idea to let this construct slide through unremarked? Or
should javac acknowledge the inherent imprecisions in the
operations leading to the exactly-integral result?

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
taqmcg@gmail.com
Guest
Posts: n/a
 
      11-15-2013
On Thursday, November 14, 2013 8:19:27 PM UTC-5, Eric Sosman wrote:
> On 11/14/2013 6:31 PM, Eric Sosman wrote:
>
> As a more concrete example,
>
> static final double FOO = 17.316;
> static final double BAR = 8.658;
> int i = FOO / BAR; // Should javac be silent here?
>
> Neither the numerator nor the denominator can be represented
> exactly as stated, yet the quotient is (probably; cook up your
> own numbers if mine are faulty) exactly 2.0. Would it be a
> good idea to let this construct slide through unremarked? Or
> should javac acknowledge the inherent imprecisions in the
> operations leading to the exactly-integral result?


In this case it's pretty clear that the error should be signaled since we have a floating point expression that involves computations where roundoff'scould do weird things:
Consider the case when we use FOO = 3.3 and BAR = 1.1. Then the value of
(int) (FOO/BAR) == 2
and I certainly wouldn't want to have a language where

int i = 3.3/1.1;
gives a different result than
double x = 3.3;
double y = 1.1;
int i = x/y;

When the integer value of the ration is a power of 2, then the internal floating point representations will differ only in the exponent, so you're likely get 'correct' values when you do the computation, but for all other integer ratios the actual value that a proper Java program would computer will often differ from the 'correct' value. And even for powers of two one isgoing to run into problems if denormalized floats or doubles are being used.

If we exclude expressions there would be still hard cases:
E.g., if we were allowing
int i = 2.0;
presumably we'd also want to allow
int i = 1.234E3; // = 1234)
but then you might be surprised to get an error for the equivalent
int i = 1.2345E3; // = 1234.5
which doesn't really look very differnt.

And what would one do with:

int i = 123456789.f;

which seems like a normal integer, but since we've gone beyond the precision of floats we'd find that
float f = 123456789.f;
int i = (int) f;
yields
i == 123456792


We wouldn't run into this when converting doubles to ints, but a similar problem occurs for doubles to longs.

So any relaxation of the rule that there is a loss-of-precision error in converting floating point values to integral values would have to be either arbitrarily limited (say to |integers| < 100) or hedged with lots of caveats.. Having a simple rule that you need to signal such a conversion with a cast seems like a reasonable choice.

Personally I'd have preferred that Java be fully consistent here and not have the exception for operators like +=

double x = 1.;
int i = 0;
i += x; // is legal

but I believe that exception is essentially required by the (imho) folly ofautomatic promotion of bytes, shorts and chars to ints.

Regards,
Tom McGlynn
 
Reply With Quote
 
Michael Jung
Guest
Posts: n/a
 
      11-15-2013
Gene Wirchenko <(E-Mail Removed)> writes:
> On Thu, 14 Nov 2013 20:39:42 +0100, Michael Jung
> <(E-Mail Removed)> wrote:
>>(E-Mail Removed)-berlin.de (Stefan Ram) writes:

[...]
>>> But then, »int i = 2.0;« gives an error, even though the
>>> compiler should see that »2.0« can be represented as an int.

>>You are right that x+1 is "promoted" to int and the second assignment
>>fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
>>This concerns constant expressions first and the second allows a
>>narrowing in rare cases, of which the first line is one but the
>>"int i = 2.0" isn't.

> Why isn't it though?


Since compile-time constant expressions are FP-strict and could be done,
I guess it was seen as pathological and not worth the effort.

Michael
 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      11-16-2013
Patricia Shanahan <(E-Mail Removed)> writes:
>I think the difference is that there is a cast-free way of initializing
>an int to the value 2.
>On the other hand, without the special narrowing rule for initializers,
>there would be no cast-free way of initializing a byte with the value 2.


It's the same in C++:

char c{ 7 }; // ok
char d{ 999 }; // usually an error
int i{ 3.0 }; // error

. Bjarne Stroustrup writes:

»The way C++11 avoids a lot of incompatibilities is by
relying on the actual values of initializers (such as 7
in the example above) when it can (and not just type)
when deciding what is a narrowing conversion. If a value
can be represented exactly as the target type, the
conversion is not narrowing.«

»Note that floating-point to integer conversions are
always considered narrowing -- even 7.0 to 7.«

http://www.stroustrup.com/C++11FAQ.html

 
Reply With Quote
 
Michael Jung
Guest
Posts: n/a
 
      11-17-2013
Patricia Shanahan <(E-Mail Removed)> writes:

> On 11/15/2013 10:24 AM, Michael Jung wrote:
>> Gene Wirchenko <(E-Mail Removed)> writes:
>>> On Thu, 14 Nov 2013 20:39:42 +0100, Michael Jung
>>> <(E-Mail Removed)> wrote:
>>>> (E-Mail Removed)-berlin.de (Stefan Ram) writes:

>> [...]
>>>>> But then, »int i = 2.0;« gives an error, even though the
>>>>> compiler should see that »2.0« can be represented as an int.
>>>> You are right that x+1 is "promoted" to int and the second assignment
>>>> fails. In the other cases the compiler will follow JLS 15.28 => 5.2.
>>>> This concerns constant expressions first and the second allows a
>>>> narrowing in rare cases, of which the first line is one but the
>>>> "int i = 2.0" isn't.
>>> Why isn't it though?

>> Since compile-time constant expressions are FP-strict and could be done,
>> I guess it was seen as pathological and not worth the effort.

> I think the difference is that there is a cast-free way of
> initializing an int to the value 2.


Not if you wanted to do "int a = 2 * 0.5;" or something similar.

> On the other hand, without the special narrowing rule for
> initializers, there would be no cast-free way of initializing a byte
> with the value 2.


They could have spent a suffix "B/b" (for non-hex integer literals) as
with "l/L".

Michael
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how can i solve this problem " char a=keyboard.readInt();" possible loss of precissio fernie.java General Computer Support 0 01-13-2008 09:22 PM
Possible Loss of Precision - not caused by type conversion Thomas Java 22 07-10-2007 11:08 AM
loss of precision in doing file I/O giff C++ 15 06-02-2006 09:22 PM
Loss of precision assigning floating point values? BigMan C++ 16 04-13-2005 07:08 PM
Can I force precision loss? stevek Java 4 01-17-2005 11:39 AM



Advertisments