Floats and Ints¶
Manipulating numbers is one of the most important and useful things a computer
can do. We’ll look at two number types in this course: int
for integers
(i.e. whole numbers), and float
for floating point numbers, i.e. numbers a
decimal point in them.
Integers¶
In Processing, an int
is a whole number (i.e. an integer), such as:
4
-61
0
183993
These are called int literals to distinguish them from variables of
type int
. For example:
int age = 18;
This statement does two things:
- It declares
age
to be a variable of typeint
. - It assigns the value
18
toage
. Since this is the first value assigned toage
, we say it initializesage
.
Keep in mind that age
is a variable of type int
, while 18
is an
int
literal. We usually refer to both as int
s, but sometimes the
distinction matters.
Integer Arithmetic¶
You can perform arithmetic on int
s using the basic arithmetic operators.
For example:
int averageLifespan = 82; // for Canadians
println(2014 + averageLifespan - 18); // 2078
Or:
int minsInOneHour = 60;
int hoursInOneDay = 24;
int daysInOneYear = 365;
int minsInOneYear = minsInOneHour * hoursInOneDay * daysInOneYear;
println(minsInOneYear); // 525600 --- about half a million minutes in a year
Integer Division¶
Dividing two int
s always returns an int
in Processing. For
example:
println(1 / 2); // 0
println(3 / 2); // 1
println(4 / 2); // 2
It might come as a surprise that 1 / 2
evaluates to 0. The “correct”
answer is 0.5, but the problem is that 0.5 is not an int
(it’s a
float
). So, after Processing divides two int
s, if the result has
any non-zero digits to the right of the decimal point they get truncated (i.e.
chopped off). This is called integer division: dividing two int
s
always returns an int
.
There is one exception, though. Dividing by 0
is an undefined operation in
mathematics, and in Processing it causes an error, e.g.:
println(5 / 0); // ArithmeticException: / by zero
This statement crashes the program and issues the error message “ArithmeticException: / by zero”.
Min and Max Integers¶
It is important to know that there is a min int
and a max int
:
println(Integer.MIN_VALUE); // -2147483648
println(Integer.MAX_VALUE); // 2147483647
As this shows, the maximum value for an int
in Processing is, exactly,
the number 2147483647
, which is a little over 2.1 billion. Similarly, the
smallest int
is a little less than -2.1 billion.
This means is that you cannot represent, say, the number 2.5 billion using an
int
. It can also result in some weird calculations, e.g. here’s what
happens if you add 1 to the maximum int
:
println(2147483647 + 1); // -2147483648
This is pretty disturbing when you think about it: by adding two positive numbers together we got a negative number!
Here’s another strange behaviour:
println(2147483648); // literal out of range
2147483648
is one more than the max int
, so it is not an int
. This
program doesn’t even run: You get a “literal out of range error” when you
compile this statement.
Another fact about int
s is that there is one more negative int
than
positive int
. The smallest int
is \(-2^{31} = -2147483648\), but
the biggest int
is only \(2^{32}-1\). One place were this might be a
small problem is the abs(x)
function, that should return x
if x >=
0
, and -x
if x < 0
. But the problem is what is abs(-2147483648)
?
The correct answer is 2147483648, but 2147483648
is not an int
: it’s
too big! In this one case, the abs
function cannot possible return the
right answer, and so it does this:
println(abs(-2147483648));
// -2147483648
Note
Processing has a bigger integer type called long
, which can
represent any integer in the range -9,223,372,036,854,775,808 to
9,223,372,036,854,775,807. That’s about -9.2 quintillion to 9.2
quintillion.
You may be interested to know that 9223372036854775807 has its own Wikipedia page, but -9,223,372,036,854,775,808 doesn’t.
If you need integers bigger than long
, then Java (on which Processing
is based) has a special type called BigInteger that
can represent arbitrarily long integers that are limited only by the amount
of memory in your computer.
The Mod Operator¶
There’s one other useful int
operator you should know about: the %
operator, which is called the mod operator, or the remainder operator.
For instance:
println(5 % 2); // 1
println(6 % 2); // 0
println(14 % 8); // 6
The expression 5 % 2
is read “5 mod 2”, and it calculates the remainder
when 5 is divided 2: since 2 goes into 5 two times with 1 left over, 5 % 2
equals 1.
One application of %
is to test if a number is even or odd. For example,
178 % 2
is 0, which means 178
is even (because 2 goes into 178 exactly
89 times with 0 left over). In general, if n
is a positive int
and n
% 2
is 0, then n
must be even. The only other possibility is that n %
2
is 1, which means n
is odd.
Here’s an example of you might use %
in animation. This program makes a
ball wrap-around the screen without using an if-statement:
float x;
void setup() {
size(500, 500);
}
void draw() {
background(255);
ellipse(x, 250, 100, 100);
x += 2;
x = x % 500;
}
Floating Point Numbers¶
In Processing, a float
is a number with a decimal point in it, such as:
4.5
-61.2
0.0
-3.0
183.993
These are examples of float literals, which are so-named to
distinguish them from variables of type float
. For example:
float speed = 1.8;
Here, speed
is a variable of type float
, while 1.8
is a float
literal. Just as for int
s, this statement does two things:
- It declares
speed
to be a variable of typefloat
. - It assigns
speed
the initial value of1.8
.
Floating Point Arithmetic¶
In most cases, floating point arithmetic works like regular arithmetic. For example:
println(1.2 + 3.2); // 4.4
println(6.0 - 3.344); // 2.7
println(2.1 * 3.14); // 6.594
println(-18.6 / 29.1); // -0.63917524
println(10.0 / 2.0); // 5.0
Notice that 10.0 / 2.0
evaluates to 5.0
, which is a float
.
Whenever you divide two float
s, the result is always a float
.
However, there are a few important details you need to be aware of.
Division by 0.0¶
Dividing a number by 0.0 is undefined mathematically, but for a float
we
get a surprising result:
println(5.6 / 0.0); // Infinity
There is no error message here — the actual result is a special float
value called infinity. Another special float
value occurs in this case:
println(5.6 / 0.0 - 5.6 / 0.0); // NaN
Again, this does not cause an error, but instead prints the special float
value NaN
, which means “not a number”.
If you think about this, it leads to a strange conclusion: if x
is a
float
, then it is possible that x - x
is not equal to 0.0
!
The reasons when and how float
s use these special values are quite
technical and beyond the scope of the course. The important thing for us is to
know that these values exist and can occur in ordinary calculations.
Min and Max floats¶
The smallest and largest float
values are as follows:
println(Float.MIN_VALUE); // 1.4E-45
println(Float.MAX_VALUE); // 3.4028235E38
Notice a few things here:
- The numbers
1.4E-45
and3.4028235E38
are written in exponential notation, and are equivalent to \(1.4 \times 10^{-45}\) and \(3.4028235 \times 10^{38}\). - The min
float
is1.4E-45
, and it is traditionally called machine epsilon. It is, approximately, the smallest possible number that we can represent as afloat
. Any positive number less than1.4E-45
is treated as equivalent to 0.0. - The max value,
3.4028235E38
, is a huge number with 39 digits in it. However, only the first 8 or so digits are significant, i.e. after 8 digits all the digits are 0. - The smallest
float
is-3.4028235E38
, which is just the negation of the maxfloat
.
Rounding Errors¶
A major problem with floating point numbers is that they are often unavoidably
inaccurate. For example, in mathematics
\(\frac{1}{3} = 0.3333 \dots\), where the \(\ldots\) means there are
an infinite number of 3s after the decimal point. But a Processing
float
can’t have an infinite number of digits:
println(1.0 / 3.0); // 0.33333334
As you can see, there are a finite number digits, plus the final digit has been rounded to 4. So it is not exactly equal to \(\frac{1}{3}\), but is instead a little bit bigger.
For many programs, round-off errors don’t make any noticeable difference. But sometimes they can be the source of serious bugs that are very hard to fix. There is an entire sub-field of computer science called numerical analysis that studies how to do accurate and efficient floating point arithmetic on machines.
In this course, we will usually just ignore round-off errors and hope that our floating point calculations are accurate enough.
Mixing ints and floats¶
You can often use int
s and float
s together without a problem. For
example:
println(4.0 + 5); // 9.0
In the expression 4.0 + 5
, 4.0 is of type float
, and 5
is of type
int
. Processing doesn’t actually know how to add float
and int
,
so it automatically converts 5 into the float
5.0
. This makes the
expression equivalent to 4.0 + 5.0
, which is 9.0
.
You can also assign an int
to a float
without error, e.g.:
float temperature = 21; // 21 is an int, but temperature is a float
This works because Processing automatically converts 21
to 21.0
.
By default, you cannot assign a float
to an int
:
int age = 5.5; // compiler error
This statement fails to compile because 5.5
is of type float
, and you
are not allowed to store a float
in an int
variable. However, you can
explicitly convert 5.5
to a float
like this:
int age = int(5.5);
println(age); // 5
Summary Table¶
int
float
Sample literals 4, -5, 0 -4.0, 3.14, 0,0 Min -2147483648 -3.4028235E38 Max 2147483647 3.4028235E38 Smallest positive 1 1.4E-45 When dividing by 0 run-time error infinity or NaN Special values none infinity, NaN
Questions¶
Give an example of:
- a positive
int
literal - a negative
int
literal - an
int
literal that is neither positive nor negative - statement that declares a new
int
variable and initializes it to 15
- a positive
What does this print?
println(5 * (1/2 + 1/3 + 1/4 + 1/5));
In regular arithmetic, \(\frac{5}{\frac{1}{2}} = 5 \cdot \frac{2}{1} = 10\). What does the equivalent expression,
5 / (1 / 2)
, evaluate to in Processing?What is the biggest possible
int
? You answer should be accurate to within about 2 million.Suppose
n
is a positiveint
. Is the expressionn + 1
always greater than 0? Why, or why not?What is the name of the
%
operator?What are the values of the following expressions?
8 % 2
8 % 3
17 % 4
(100 % 2) + (100 % 3) + (100 % 4)
Give an example of:
- a positive
float
literal greater than 100 - a positive
float
literal between 0 and 1 - statement that declares a new
float
variable and initializes it to 3.14
- a positive
How many digits are there in the maximum possible
float
value? Your answer should be correct within 1 digit.What does
NaN
stand for?What does this print?
println(91.22 / 0.0);
Give a simple example of an expression involving
float
s that suffers from a round-off error.What does this print?
println(91.22 / 0);
What does this print?
println(int(6.9) + 3);
Answer “true” or “false” for each of the following questions:
- If
n
is a positiveint
, thenn + 1
is also a positiveint
. - If
a
andb
are both of typeint
, anda > b
is true, thena + 1 > b
is also true. - If
n
is a positiveint
, thenn - n
is0
. - If
x
is afloat
, thenx - x
is0.0
.
- If