Blue Java symbol ontop of red hue coffee beans

1.13 Java | How to Convert Numeric Type with Type Casting

Table of Contents

What is Type Casting?

  1. Type casting in Java is when you transform one type, class, or interface into another type, class, or interface.
  2. Assigning a value of one type to a variable of another type is known as Type Casting.

Without type casting, you cannot assign a value of one type to a variable of a different type.

What are the 2 Types of Type Casting?

In Java there are 2 types of Type Casting:

  1. Widening (Implicitly casted)
  2. Narrowing (Explicit casted)

Widening Type Casting involves assigning a value to a variable type that has a bigger range (small to big). This is implicitly (automatically) done by Java, so for example, Java automatically converts an integer to a floating point value. So letting Java evaluate 3 * 4.5 is the same as 3.0 * 4.5. That’s because you can always assign a value to a numeric variable whose type supports a larger range of values, in this case the integer value is assigned to the larger-ranged floating point variable type. Another example is that you can assign a long value to a float variable.

Narrowing Type Casting involves assigning a value to a variable type that has a smaller range (big to small). This is explicitly (manually) done by the programmer, so for example, you need to manually convert a floating point to an integer value. Let’s say the floating point number we want to convert into an integer is 1.7 . So the Java code to do so would look something like this:

System.out.println((int)1.7);

which displays/prints 1.

So you can see from the above example that the syntax for casting a type is to specify the target type in parentheses, followed by the variable’s name of the value to be cast.

How do I Know Which Type of Casting to use?

The ranges of the different types, from smallest to biggest:

byte < short < int < long < float < double
char < int

If you choose to assign a value with a small type range to a variable with a big type range, you use widening (implicit casting automatically done by Java). i.e. byte value to short variable.

If you choose to assign a value with a big type range to a variable with a small type range, you use narrowing (requires explicit casting from the programmer). i.e. short value to byte variable.

More Examples of Type Casting

The following statement:

System.out.println((double)1/2);

displays 0.5, because 1 is cast to 1.0 first, then 1.0 is divided by 2.

However, the statement:

System.out.println(1/2);

displays 0, because 1 and 2 are both integers and the resulting value should also be an integer.

Note that casting does not change the variable being cast. For example, d is not changed after casting in the following code:

double d = 4.5;
int i = (int) d; // i becomes 4, but d is still 4.5

Note that to assign a variable int type to a variable of the short or byte type, explicit casting must be used. For example, the following statements have a compile error:

int i = 1;
byte b = i; // Error because explicit casting is required

However, so long as the integer literal is within the permissible range of the target variable, explicit casting is not needed to assign an integer literal to a variable of the short or byte type.

*Be careful when using casting, as a loss of information might lead to inaccurate results (as a result of casting a value to a different type).

Where does Explicit and Implicit Casting Come From?

First, we need to understand how Magnitude & Precision related to casting.

Magnitude is how big of a range the data type can fit.

long data types have 64-bits, and since numbers are represented using two’s complement, signed long numbers have a valid range from -263 to 263 − 1 (that’s -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807).

float data types only have 32-bits, but numbers are represented using IEEE 754 single floating point notation, and so floats have a valid range of about ±3.4 * 1038, which is a lot larger than what a long can contain.

So the magnitude of a float is larger than that of a long.

Precision is how much of a number can be represented by a data type. For example, suppose you had two variables that you wanted to use to approximate pi, an int and a float:

int iPi = 3;
float fPi = 3.14159f;

Even though neither are really close to the actual value of pi (and no data type will ever be), fPi is more precise than iPi because it can hold more information regarding the number.

In IEEE 754 single floating point notation, 23 of the 32 bits are dedicated to what’s known as the “mantissa”, which is what’s used to represent the significant digits of a number. However, a long number can be too large to completely represented in the mantissa, so the last few parts might be truncated, resulting in the float not being the same number as the long. You can see this demonstrated in the following example:

long a = 1234567890;
float b = a;
System.out.println(a - (int)b); // prints -46 instead of 0

This is because 1234567890 loses precision when stored in the mantissa of a float.

As for why you don’t need an explicit cast – it’s just a design decision the makers of Java made. They decided that operations which lose information about the magnitude require an explicit cast, while operations which lose precision don’t. [Source]

TL;DR:

1000 has bigger Magnitude(range)
.1000 has bigger Precision

You need use explicit casting when casting to a type that has a smaller magnitude.
Otherwise, Type Casting in Java ignores precision.

What's Your Opinion?