Algorithms and OOD (CSC 207 2014F) : Readings
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [Learning Outcomes] [FAQ] [Teaching & Learning] [Grading] [Rubric] - [Calendar]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Examples] [Handouts] [Labs] [Outlines] [Readings]
Reference: [Student-Curated Resources] [Java 8 API] [Java 8 Tutorials] [Code Conventions]
Related Courses: [CSC 152 2006S (Rebelsky)] [CSC 207 2014S (Rebelsky)] [CSC 207 2014F (Walker)] [CSC 207 2011S (Weinman)]
Misc: [Submit Questions] - [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)] [Issue Tracker (Textbook)]
Summary: We introduce (or re-introduce) numbers in the Java programming language, focusing on a selection of useful operations.
Prerequisites: Basics of Java and Strings in Java.
Important Classes
Almost every modern programming language permits programmers to use variables of one or more numeric data types. Not so surprisingly, most also provide a variety of representations of numbers so that programmers can choose the ones that are most appropraite for the task at hand.
One important question is whether one accepts a fixed amount of memory for numeric values or prefers to permit memory to be allocated depending on the size of the number. If you limit yourself to a fixed amount of memory (as most languages do for the basic numeric types), one can only represent a limited number of values. If you permit memory to be allocated on the fly, you complicate operations (usually making them more costly in terms of time).
In Java, the primitive types long
, int
,
and short
each represent integers with a
fixed amount of memory. The range of legal values for
long
is -2^{63} to
2^{63}-1. The range of legal values
for int
is -2^{31} to
2^{31}-1. The range of legal values
for short
is -2^{15} to
2^{15}-1. You can represent constant values
in each of these types by writing the digits of the value, potentially
prefixed by a “minus sign”.
In Java, the primitive types double
and float
represent approximations of real numbers. The range of each
is difficult to describe, particularly as they approximate different sizes
of values differently. Beginning programmers should generally use
double
. You represent constant values of these types using
the digits, including a possible decimal point. (Other notations are
also available. We will introduce them as necessary.)
Note that we have referred to all of these types as “primitive”. This term suggests that they are the basic building blocks upon which other types in the language are built. It also suggests that they may have a lower-level implementation than do other types, which generally makes computation with primitive types more efficient.
Here are a few simple declarations of primitive numeric names and values.
int x = 5; double pi_approx = 3.1415;
Java allows you to compute with the various primitive types of
values. The binary arithmetic operations (addition, subtraction,
multiplication, and division) are written with the natural symbol
(+
, -
, *
, and /
)
in standard infix form. (The term “infix” means that
the operation is written between the two operands. It is contrasted
with “prefix”, in which the operation appears before the
operands, and “postfix”, in which the operation appears
after the operands.)
For example, to add 2 to x
and assign the result to
y
, you would write
y = x + 2;
Java understands precedence and associativity, so you can also combine operations in a single expression and have a predictable result, as in
pen.println(3 + 4 * 5); // prints 23 pen.println(3 - 1 - 1); // prints 1
Numbers, like strings, are comparable. You can compare two numbers
to determine whether the first is less than (<
),
less than or equal to (<=
), equal to
(==
), greater than or equal to (>=
),
greater than (>
) or not equal to (!=
)
another numeric values.
In all cases, the comparator goes between the new numbers, as in
x < 5
or (y-j > 1.0)
.
It is generally considered a bad idea to compare two floating point approximations of real numbers for exact equality or inequality. Instead, one should take the absolute value of their difference and compare that to a relatively small value.
What do you do if you want to perform more complex mathematical
calculations, such as finding square roots? You use the useful
class java.lang.Math
. You should refer to the documentation for that class
for more information.
Because java.lang.Math
is primarily a utility class,
when you call methods in that class, you typically write write
Math.methodName(params)
,
as in
double root; root = Math.sqrt(x);
Most of the time, Java will permit you to use different numeric types and “coerce” a value to the appropriate type. For example, if you assign an integer to a double, it will convert the integer to the corresponding double (e.g., 5 to 5.0) before assigning. Similarly, if an operation has two different paramater types (e.g., you add an integer and a float), it will convert the less-general type to the more-general type.
You should be careful about such conversions, as they can lead to slight changes in your data (particularly as you use the approximation types). Strive to use the types you need and to stay within those types in thee expressions you write.
For each primitive numeric type, Java also has a corresponding class.
These classes are java.lang.Short
,
java.lang.Integer
, java.lang.Long
,
java.lang.Float
, and java.lang.Double
.
All are based on the more general class java.lang.Number
.
Each class also provides an appropriate constructor (e.g., one
constructor for Integer
accepts an int
as a parameter) and a toString
method that gives a
representation of the value as a sequence of characters appropriate
for output. Most also provide a constructor that takes a string as
a parameter and “parses” it to extract the number.
For example,
Double d; d = new Double(3.2); Integer i; i = new Integer("3123");
More recent versions of Java add the capability to automatically “box” and “unbox” numeric values - convert from the primitive representation to the object and back again.
Integer i = 3.14; int j = i;
The general Number class (and therefore all the related classes) provides
a number of conversion methods, including shortValue
,
intValue
, longValue
, floatValue
,
and doubleValue
. Each of these methods returns a value of
the specified type.
For example,
Double d; d = new Double(3.14); float f; f = d.floatValue();
Because some progams need values that go beyond the
ranges of the primitive types (ranges that are duplicated
by the corresponding number classes), Java also provides
two kinds of “arbitrary size” numbers: java.math.BigDecimal
and java.math.BigInteger
.
These classes provide their own methods for the basic arithmetic and
comparison operations. The basic operations are add
,
subtract
, multiply
, and divide
.
The operations are written in the object-oriented object dot
method format. For example, you to multiply x
by y
and then add z
, you might write:
BigInteger result, x, y, z; ... result = x.multiply(y).subtract(z);
These methods are necessarily less efficient than those for the
primitive classes. Nonethless, if you need to represent numbers
beyond the normal ranges (or with greater precision, in the case of
BigDecimal
, they are excellent options.