Friday, 19 May 2017

Tutorial 15: Casting Numerical Values



Remember in the tutorial on datatypes in Java, I told you that when we say:
int j = 40;

We are telling Java to create enough room to hold an integer value and then assign a value of 40 to that integer variable. 

I also told you that the difference between the different datatypes used in Java is the type of data they hold and the size. Right?

Great! So let us look at some examples: Numbers or numeric values can be held by short integers, integers, long integers, float and double. What is the difference between these datatypes? Let me copy a table that we looked at in the datatypes tutorial:


Minimum value
Maximum value
Size
short
-215
+215-1
16 bits
int
-231
+231-1
32 bits
long
-263
+263-1
64 bits
float
1.4E-45
3.4028235E38
32 bits
double
4.9E-324
1.7976931348623157E308
64 bits
Table 1: The minimum, maximum and bit sizes of different numerical datatypes in Java.

Notice the minimum and maximum values that these datatypes can hold. Also note the sizes of the datatypes in bits and you will notice that some hold smaller values than others. Now for the purposes of this tutorial, let me give a very simple example that will open up the soft fluffy heart of the concept that hides behind the scary name “casting.”

I know you have buckets of different sizes in your home. If you fill up a small 10-liter bucket with water, then it is perfectly alright to transfer the water to a larger bucket that can hold 20 liters of water. Why? Because the larger bucket will hold all the water that was originally in the 10-liter bucket and still have some room left.

Now consider the opposite scenario. Let’s say that you have filled your 20-liter bucket with water. But for some reason, you want to transfer this water to another bucket. Can you transfer all the water in the 20-liter bucket to the 10-liter bucket? No…. you can’t. In fact, if you try to transfer all water from the larger bucket to the smaller bucket, some water will spill over and you will end up losing a whole 10 liters of water.

The same logic applies in Java only that instead of buckets, we have datatypes and instead of water, we have information. 

So let’s say that you have a short integer and you want to copy its contents into a datatype that can hold more information such as long integer. Here is how you would do it:
short s = 40;
long h = s;

This is very okay because we are not losing any information. long integers can hold more data than short integers.

However, if you try to do this, Java will complain:
long longValue = 6678;
short shortValue = longValue;

Why will Java complain? Java complains because by doing the above operation, we will lose some information. We want to store the information that was in a 64-bit datatype to a 16-bit datatype. And information, like water, is valuable.

So what if you are sure that you really want the information stored in the long integer to be stored in the short integer? What if you are sure of what you are doing and its repercussions? Here is how you tell Java that you know what you are doing:

long longValue = 6678;
short shortValue = (short) longValue;

You precede the value that you want to pass to the shortValue with the word short enclosed in parentheses. This tells Java that you are aware that by performing the above operation, you are sure of what you are doing, that it wasn’t an error or a typo. And subsequently, Java stops complaining. 

Here is another example. Say you have data stored in a double variable. How can you cast it to all the smaller datatypes below it without getting an error or warning from Java?
double doubleValue = 47895.356789;
float floatValue = (float) doubleValue;
long longValue = (long) doubleValue;
int intValue = (int) doubleValue;
short shortValue = (short) doubleValue;

Now, what if you wanted to pass a value assigned to a smaller datatype to a larger datatype? Say you have a short integer with a value assigned to it. How do you pass it to the other numerical datatypes that are larger in size than itself?
short shortValue = 15;
int intValue = shortValue;
long longValue = shortValue;
float floatValue = shortValue;
double doubleValue = shortValue;

So you see, when you are passing the value contained in a smaller datatype to a larger datatype, Java does not complain and carries out the operation alright. However, when you are passing the value contained in a larger datatype to a smaller datatype, Java will do the operation, but first, you need to tell Java that you are sure about what you are doing and that you risk losing some data if you proceed with the operation. And how do you tell Java you are sure you actually want to cast from a larger datatype to a smaller datatype? You precede the value that you are passing to the smaller datatype with the identity or type of the smaller datatype.

Below is an example of both scenarios. I’ve also included a screenshot showing how Java complains when you are risking losing information by casting from a larger datatype to a smaller datatype.



Figure 1: How to cast from a smaller datatype to a larger datatype.
Figure 2: How to cast from a larger datatype to a smaller datatype.

Figure 3: This is the warning that Java gives you when you try to cast from a larger datatype to a smaller datatype.

I hope that you have seen that casting is just a concept we use in our daily lives, sometimes even without noticing. But at its core, it is a really simple concept. 

In the next tutorial, I am going to show you how to create a program that reads data from a file. 

In case you have any questions or comments, please drop them in the comments section below and I will make sure I address them.

Until next time, stay safe.

No comments:

Post a Comment