# int -> float -> int and loss of precision

Ruben Soto
Ranch Hand
Posts: 1032
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
The confusion continues:

Output is:
a1 = 2147483647 af = 2.14748365E9 a2 = 2147483647

Ruben Soto
Ranch Hand
Posts: 1032
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
I still have not understood why its returning true?

Ruben Soto
Ranch Hand
Posts: 1032
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
Thanks..Ruben.

Ruben Soto
Ranch Hand
Posts: 1032
You're welcome, Abhi. There are so many things to learn...

Abhi vijay
Ranch Hand
Posts: 509
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: 826

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
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: 826
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

why is this giving error, 32 does fall in the range of int.

sudipto shekhar
Ranch Hand
Posts: 826
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
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
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
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
@Bert
Thanks for the tips which you give time to time.

Naveen

sudipto shekhar
Ranch Hand
Posts: 826
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
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
• 1
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
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: