Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

int -> float -> int and loss of precision

 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I got this from one of Enthuware's SCJP 1.6 exams:

float f = Integer.MAX_VALUE;
int i = (int) f;
System.out.println( i == Integer.MAX_VALUE);

This will print true. But why? The float and int primitive types have the same bit depth, but surely there must be some potential loss of precision when storing an int in a float. The float type has the same bit depth, but it must be able to store more values, since it can store decimals as well as the integer part. I wonder if there is any reliable and rational way to distinguish when there is and there is not loss of precision.
[ December 24, 2008: Message edited by: Ruben Soto ]
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The confusion continues:


Output is:
a1 = 2147483647 af = 2.14748365E9 a2 = 2147483647
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think I know what's happening. When you assign primitives you just copy the bit pattern, and that's why there is no loss of precision doing int to float to int assignments. Could anyone confirm?

Thanks!
 
Abhi vijay
Ranch Hand
Posts: 509
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I still have not understood why its returning true?
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Abhi,

I think this is the reason why:

A primitive variable is just a bunch of bits with a type associated to it. The type determines the meaning of the bits.

When you assign a primitive variable to other primitive variable, what you do is copy the bits (in the case of float and int, since both are 32 bit entities, that's exactly what happens, without truncation or padding by zero bits to the left, which happens when you assign something that's bigger or smaller to a variable of a different bit-depth type.)

So, the bits remain the same. When you assign the int to the float, the bits remain the same (but the value reported by the float is different, since the meaning of the value for a bit pattern of a float type is different than the meaning of the value for a bit pattern of an int type.)
However, when you assign from the float to another int, the bits still are the same as those in the first int, and that's why the value is the same.

I know this is a little confusing, but I hope the explanation helped.
[ December 24, 2008: Message edited by: Ruben Soto ]
 
Abhi vijay
Ranch Hand
Posts: 509
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks..Ruben.
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're welcome, Abhi. There are so many things to learn...
 
Abhi vijay
Ranch Hand
Posts: 509
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree..Ruben.The questions are so tricky.
I just saw a question in one of the posts.



Why does the compilation fail in case of long?
 
sudipto shekhar
Ranch Hand
Posts: 823
Chrome Eclipse IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


This code will not compile and say possible loss of precession. Why? Because i is assigned a value that is out of the range of short (0-32767). In this case an explicit cast is required.
When l is given the value 23L it is of 64-bit which does not fit into an int.
 
Abhi vijay
Ranch Hand
Posts: 509
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sudipto, If that is the case then how does 32 bit int fit into 16 bit short without any explicit cast???
 
sudipto shekhar
Ranch Hand
Posts: 823
Chrome Eclipse IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Remember short is a int but the value that can be stored in a short is 0-32767.
The value, if increases than 32767 ,it can't be stored in a short as short can store a int between the range 0-32767. It would then require an explicit casting.

See this code. a byte is assigned an int. The range of byte is0-127. The code works fine.


But when the value of j is changed to 128 it requires a casting! Why? Because j contains a value that is bigger than the value that a byte can store.

Hope this explains.
 
Abhi vijay
Ranch Hand
Posts: 509
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


why is this giving error, 32 does fall in the range of int.
 
sudipto shekhar
Ranch Hand
Posts: 823
Chrome Eclipse IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
going through this i found


Integer literals are 32-bit int values unless they end with the character L or l, in which case they are 64-bit long values:

1234 // An int value
1234L // A long value



But when I try this code

it does not work!
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Automatic narrowing in primitives only works for compile constant values, and it only works from int to smaller values, not for long, float, or double. Also, in order for it to work implicitly the compiler must be able to determine (therefore, this must be determined at compile time) that the value will fit in the variable without loss of information.
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Added later: (Please refer Khaled Mughal Chapter 3)
Implicit narrowing conversions on assignment can occur in cases where all the following conditions are met:

1. the source is a constant expression of either byte, short, char or int type
2. the destination type is either byte, short or char type
3. the value of the source is determined to be in the range of the destination type at compile time.



Added later: Moreover, Bert has clarified below that this topic is not on the 1.5/1.6 exam. Still i've typed this explanation just to share some knowledge
[ December 25, 2008: Message edited by: Harvinder Thakur ]
 
Bert Bates
author
Sheriff
Posts: 8898
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
FWIW -

This topic *might* possibly be found on the 1.4 exam, but it won't be found on the 1.5 or 6 exam.

ho ho ho,

Bert
 
nav katoch
Ranch Hand
Posts: 246
Eclipse IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Bert
Thanks for the tips which you give time to time.

Naveen
 
sudipto shekhar
Ranch Hand
Posts: 823
Chrome Eclipse IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As being an aspirant of SCJP myself I know that the topic is not in 1.5 exam.
But just being in the forum of SCJP does not mean it cannot be discussed... Only the forum is wrong.

Any ways Happy New Year to all of you..Have a nice and safe celebration .
 
awad saleh
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I really Thanks allot Harvinder Thakur AND sudipto shekhar and all others.......
[ December 26, 2008: Message edited by: awad saleh ]
 
meera kanekal
Ranch Hand
Posts: 75
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
Contrary to some of the inputs given in this discussion the following program compiled and gave the following output:
This is my own code
public class Casting {

public static void main(String[] args) {
byte b = 5;
byte c = 3;
//byte d = b+c;
byte d = (byte) (b + c);
System.out.println("Casting is necessary even when you add 2 bytes "+d);

int i = 127;
//byte e = i;
byte e = (byte)i;
System.out.println("Casting is necessary for Narrowing conversions of int to byte "+e);

int j = 128;
byte f = (byte) j;
System.out.println("byte capacity is smaller "+f);

int k = 32700;
short s = (short)k;
System.out.println("Narrowing conversion of int to short requires casting "+s);
final int m = 32700;
short sh = m;
System.out.println("Narrowing conversion of int to short requires NO casting because int is final and a " +
"compile time constant "+sh);

int a1 = Integer.MAX_VALUE;
float af = a1;
int a2 = (int) af;
System.out.println("int-float-int conversion a1 = " + a1 + " af = " + af + " a2 = " + a2);

long l1 = 32l;
// int n = l1;
int n = (int)l1;
System.out.println("long to int narrowing conversion "+n);

final long l2 = 1000L;
int p = (int)l2;
System.out.println("long to int narrowing conversion:" +
" long does not have to be final "+p);

long l3 = 130l;
byte g = (byte)l3;
System.out.println(" long to byte narrowing conversion. byte capacity is smaller "+g);
}

}

Casting is necessary even when you add 2 bytes 8
Casting is necessary for Narrowing conversions of int to byte 127
byte capacity is smaller -128
Narrowing conversion of int to short requires casting 32700
Narrowing conversion of int to short requires NO casting because int is final and a compile time constant 32700
int-float-int conversion a1 = 2147483647 af = 2.14748365E9 a2 = 2147483647
long to int narrowing conversion 32
long to int narrowing conversion: long does not have to be final 1000
long to byte narrowing conversion. byte capacity is smaller -126


Thanks,
Meera
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know that, as Bert mentioned, this is not on the exam, but I would like to correct a mistake.

My theory was that when you assign an int to a float, then back to an int, the bit pattern remained unchanged, because that's what seemed to be the case.

After further testing, that appears not to be the case. The Integer.MAX_VALUE
"lossless" roundtrip conversion seems to be a fluke, and not the norm. Run the following code and you will understand:

 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic