|
|
|
|
![]() |
|
|||
|
![]() See the Winners! ![]()
|
Other data types Although all data in a computer is stored in
numeric format, some data types conceptually have nothing to do with numeric
values, but deal only with the concept of true or false
or with the concept of the letters of the alphabet and the punctuation characters.
I will have more to say about these types later. Type specification For every different type of data used with a particular programming language, there is a specification somewhere that defines two important characteristics of the type:
What do I mean by instance?
We might say that an instance is the physical manifestation of a plan or a type. Using mixed types Somewhat secondary to this specification, but also extremely important, is a set of rules that defines what happens when you perform an operation involving mixed types (such as making a purchase using some yen currency in combination with some dollar currency). However, that is beyond the scope of this tutorial, so I won't get into it here. An example, the short data type There is a data type in Java, C++, and C# known as short. If you have an instance of the short type in Java, the set of all possible values that you can store in that instance is the set of all whole numbers ranging from -32,768 to +32,767. This constitutes a set of 65,536 different values, including the value zero. No other value can be stored in an instance of the type short. For example, you cannot store the value 35,000 in an instance of the type short in Java. If you need to store that value, you will have to use some type other than short. Sort of like an odometer The short type is an integer type. Integer types are somewhat analogous to the odometer in your car (the thing that records how many miles the car has been driven). For example, depending on the make and model of car, there is a specified set of values that can appear in the odometer. The value that appears in the odometer depends on how many miles your car has been driven. It is fairly common for an odometer to be able to store and to display the set of all positive values ranging from zero to 99,999. If your odometer is designed to store that set of values and if you drive your car more than 99,999 miles, it is likely that the odometer will roll over and start back at zero after you pass the 99,999-mile mark. In other words, that particular type of odometer does not have the ability to store a value of 100,000 or more miles. Once you pass the 99,999 mark, the data stored in the odometer is corrupt. It no longer represents the true number of miles for which the car has been driven. A word or two about operations Assume that you have two instances of the type short in a Java program. Here are some of the operations that you can perform on those instances:
What if you want to do something different? If you want to perform an operation that is not allowed by the type specification, then you will have to find another way to accomplish that purpose. For example, some programming languages allow you to raise whole-number types to a power (example: four squared, six cubed, nine to the fourth power, etc.). However, that operation is not allowed by the Java specification for the type short. If you need to do that operation with a data value of the Java short type, you must find another way to do it. Two major categories of type Java data types can be subdivided into two major categories:
Primitive TypesJava, C++, and C# are extensible programming languagesWhat this means is that there is a core component to the language that is always available. Beyond this, individual programmers can extend the language to provide new capabilities. The primitive types discussed in this section are the types that are part of the core language. A later section will discuss user-defined types that become available when a programmer extends the language. Four categories of primitive types It seems that when teaching programming, I constantly find myself subdividing topics into sub-topics. I am going to subdivide the topic of primitive types into four categories:
Whole-number (integer) typesHopefully this categorization will make it possible for me to explain these types in a way that is easy for you to understand.The whole-number types, often called integer types, are probably the easiest to understand. These are types that can be used to represent data without fractional parts. Purchasing applesauce and hamburger For example, consider purchasing applesauce and hamburger. At the grocery store where I shop, I am allowed to purchase applesauce by the jar, only in whole-number or integer quantities. For example, the grocer is happy to sell me one jar of applesauce and is even happier to sell me 36 jars of applesauce. However, she would be very unhappy if I were to open a jar of applesauce in the store and attempt to purchase 6.3 jars of applesauce. A count of the number of jars of applesauce that I purchase is somewhat analogous to the concept of whole-number data types in Java. Applesauce is not available in fractional parts of jars, at least not at the store where I purchase my groceries. On the other hand, the grocer is perfectly willing to sell me 6.3 pounds of hamburger. This is somewhat analogous to floating-point data types in Java. Accommodating applesauce and hamburger in a program Therefore, if I were writing a program dealing with quantities of applesauce and hamburger, I might elect to use a whole number type to represent jars of applesauce and to use a floating-point type to represent pounds of hamburger. Different whole-number types Four different whole-number types are built into the Java language:
Differences in operations Although there are some subtle differences among these four types in terms of the operations that you can perform on them, I will defer a discussion of those differences until a more advanced lesson (for example some operations require instances of the byte and short types to be converted to type int before the operation takes place). Algebraically signed values All four of these types can be used to represent algebraically signed values ranging from a specific negative value to a specific positive value. Range of the byte type For example, the byte type can be used to represent the set of whole numbers ranging from -128 to +127 inclusive. (This constitutes a set of 256 different values, including the value zero.) The byte type cannot be used to represent any value outside this range. For example, the byte type cannot be used to represent either -129 or +128. No fractional parts allowed by byte type Also, the byte type cannot be used to represent fractional values within the allowable range. For example, the byte type cannot be used to represent the value of 63.5 or any other value that has a fractional part. Like a strange odometer To form a crude analogy, the byte type is sort of like a strange odometer in a new (and unusual) car that shows a mileage value of -128 when you first purchase the car. As you drive the car, the negative values shown on the odometer increment toward zero and then pass zero. Beyond that point they increment up towards the value of +127. Oops, numeric overflow! When the value passes (or attempts to pass) +127 miles, something bad happens. (The value rolls over and starts at -128 again.) From that point forward, the value shown on the odometer is not a reliable indicator of the number of miles that the car has been driven. Ranges for each of the whole-number types The table in Figure 5 shows the range of values that can be accommodated by each of the four whole-number types supported by the Java programming language.
Can represent some fairly large values As you can see, the int and long types can represent some fairly large values. However, if your task involves calculations such as distances in interstellar space (or the U.S. national debt), these ranges probably won't accommodate your needs. This will lead you to consider using the floating-point types discussed in the upcoming sections. Operations on integer types As mentioned earlier, some of the operations that can be performed on integer
types are as follows:
I will discuss other operations that can be performed on whole-number types in a subsequent lesson. Floating-point types
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
.62357185*1000 Figure 6 Different ways to represent a value |
In other words, I can represent the value as a mantissa (62357185) multiplied by a factor where the purpose of the factor is to represent a left or right shift in the position of the decimal point.
Now consider the factor
Each of the factors shown above represents the value of ten raised to some specific power, such as ten squared, ten cubed, ten raised to the fourth power, etc.
Exponentiation
If we allow the symbol ^ to represent exponentiation (raising to a
power) and allow the symbol / to represent division, then we can write
the values for the above factors in the ways shown in Figure 7. Note in
particular the numbers in blue, which I will refer to later as the exponents.
|
1000 = 10^+3 = 1*10*10*10
Figure 7 Representation of the factor |
For example, in the above notation, the term 10^+3 means 10 raised to the third power.
The zeroth power
By definition, the value of any value raised to the zeroth power is 1. (Check this out in your old high school algebra book.)
The exponent and the factor
Hopefully, at this point you will understand the relationship between the value shown in blue (the exponent) and the factor introduced earlier.
Different ways to represent the same value
Having reached this point, by using substitution, I can rewrite the original set of representations of the value 623.57185 in the different ways shown in Figure 8. (Compare Figure 8 with Figure 6.)
|
.62357185*10^+3 Figure 8 Different ways to represent a value |
It is very important to for you to understand that these are simply different ways to represent the same value.
A simple change in notation
Finally, by making a simplifying change in notation where I replace *10^
by E I can rewrite the different representations of the value
of 623.57185 in the ways shown in Figure 9.
|
.62357185E+3 Figure 9 Different ways to represent a value |
This is a relatively standard way to display floating-point values, using exponential notation (the letter E indicates an exponent).
Getting the true value
Floating-point types represent values as a mantissa containing a decimal point along with an exponent value, which tells how many places to shift the decimal point to the left or to the right in order to determine the true value.
Positive exponent values mean that the decimal point should be shifted to the right. Negative exponent values mean that the decimal point should be shifted to the left.
Advantages of floating-point types
One advantage of floating-point types is that they can be used to maintain fractional parts in data values.
Another advantage of floating-point types is that a very large range of values can be represented using a reasonably small amount of computer memory for storage of the values. For example (assuming that I counted the number of digits correctly) Figure 10 shows how to represent a very large value and a very small value as a floating-point type.
|
The very large value: 62357185000000000000000000000000000000.0 can be represented as 6.2357185E+37 The very small value: 0.0000000000000000000000000000062357185 can be represented as 6.2357185E-30 Figure 10 Representing a large range of values |
When would you use floating-point?
If you happen to be working in an area where you need to keep track of fractional parts (such as the amount of hamburger in a package), have to work with extremely large numbers (distances between galaxies), or have to work with extremely small values (the size of atomic particles), then you will need to use the floating-point types.
Two floating-point types
Java supports two different floating-point types:
| float 1.4E-45 to 3.4028235E38 double 4.9E-324 to 1.7976931348623157E308 Figure 11 Range for floating-point
types
|
Operations on floating-point types
Floating-point types support the typical arithmetic and comparison operations. I will discuss the operations that can be performed on floating-point types in more detail in a subsequent lesson.
Computers deal only in numeric values. They don't know how to deal directly with the letters of the alphabet and punctuation characters.
The purpose of the character type is to make it possible to represent the letters of the alphabet, the punctuation characters, and the numeric characters internally in the computer. This is accomplished by assigning a numeric value to each character, much as you may have done to create secret codes when you were a child. (For example, in Java an upper-case A character is represented by the numeric value 65, whereas the upper-case B is represented by the numeric value 66.)
A single character type
Java supports a single character type named char. The char type uses a standard character representation known as Unicode to represent up to 65,535 different characters.
Why so many characters?
The reason for the large number of possible characters is to make it possible to represent the characters making up the alphabets of many different countries and many different languages.
Representing a character symbolically
Although each character is represented internally by a numeric value, as long as the characters that you use in your program appear on your keyboard, you usually don't have a need to know the numeric values associated with the different characters.
In Java, you usually represent a character to the program by surrounding it with apostrophes as follows: 'A'.
The Java programming tools know how to cross-reference that specific character symbol against the Unicode table to obtain the corresponding numeric value. (A discussion of the use of the char type to represent characters that don't appear on your keyboard is beyond the scope of this lesson.)
The char type supports the typical arithmetic and comparison operations. I will discuss the operations that can be performed on the char type in more detail in a subsequent lesson.
|
if some test
returns true, then Figure 12 Typical use of boolean type |
I will discuss the operations that can be performed on the boolean type in more detail in a subsequent lesson.
As mentioned earlier, Java is an extensible programming language. There is a core component to the language that is always available. Beyond this, different programmers can extend the language in different ways to meet their individual needs. (In addition, the programmers at Sun have created a large library of user-defined types, which you can use if you have access to the library.)
Creating new types
One of the ways that individual users can extend the language is to create new types. As indicated earlier, for every different type of data used with a particular programming language, there is a specification somewhere that defines two important characteristics of the type:
1. The set of all possible data values that can be stored in an instance of the type.
2. The operations that you can perform on that instance alone, or in combination with other instances.
Thus, when creating or defining a new type, the user must define the set of values that can be stored in an instance of the type, as well as the operations that can be performed on instances of the type. From the viewpoint of this tutorial lesson, the purpose of a class definition is to create a new type, and to define the attributes of the type listed above.
No magic involved
While this might initially seem like magic, once you get to the heart of the matter, it is relatively straightforward. Instances of new types are created by combining instances of primitive types and instances of other user-defined new types.
An example
For example, the String type, which can be used to represent a person's last name, is just a grouping of a bunch of instances of the primitive char type (plus a specification of the operations that can be performed on an instance of the new String type).
A new Person type, which could be used to represent a person's first name and last name, might simply be a grouping of two instances of the user-defined String type.
The company telephone book
A programmer responsible for producing the company
telephone book might create a new Employee type that could be
used to store the first and last names along with the telephone number
of an individual. Using this new type, the programmer could create
an instance of the new type for each employee in the company.
(At this point, let me sneak a little jargon in and tell you that we normally refer to such instances as objects. More specifically, we refer to instances of primitive types as variables, and we refer to instances of user-defined types as objects.)
A comparison operation
This programmer might define one of the allowable operations for the Employee type to be a comparison between two objects of the Employee type to determine which is greater in an alphabetic sorting sense. This operation could be used to sort the set of objects representing all of the employees into alphabetical order. The set of sorted objects could then be used to print a new telephone book.
A name-change operation
Another allowable operation that the programmer might define for the Employee type would be the ability to change the name stored in an object representing an employee.
For example when Suzy Smith marries Tom Jones, she might elect to thereafter be known as Suzy Jones, Suzy Smith-Jones, or Suzy Jones-Smith. In this case, there would be a need to modify the object that represents her to reflect her newly-elected surname. (Or perhaps Tom Jones might elect to thereafter be known as Tom Smith, in which case it would be necessary to modify the object that represents him.)
An updated telephone book
The programmer could use the name-changing operation to modify the object, use the sorting operation to re-sort the set of objects, and then print and distribute a modified version of the telephone book.
Many user-defined types already exist
Unlike the primitive types which are predefined, I am unable to give you much in the way of specific information about user-defined types, simply because they don't exist until the user defines them.
I can tell you, however, that when you obtain the Java programming tools from Sun, you not only receive the core language containing the primitive types, you also receive a large library containing several thousand user-defined types that have already been defined. A large documentation package is available from Sun to help you determine the individual characteristics of these user-defined types.
The most important thing
At this stage in your development as a programmer, the most important thing for you to know about user-defined types is that they are possible in Java, C++, and C#, as well as in some other object-oriented programming languages as well.
Unlike earlier procedural programming languages such as C and Pascal, when you use an extensible object-oriented programming language, you are no longer forced to adapt your problem to the available tools. Rather, you now have the opportunity to extend the tools to make them better suited to solve your problem.
The class definition