A Programming Primer for Counting and Other Unconventional Tasks


Ruby's basic data objects for counting and math

Math is not a pre-requisite for programming.

Repeat: Math is not a pre-requisite for programming.

You don't have to be great at math to write useful programs, aside from being able to tell when one number is bigger than another and counting from 0. Remembering your high school math gets you pretty far in most applications of programming.

If you are good at math, particularly at statistics, linear algebra and number theory, you'll have a significant head start both in writing efficient code and in thinking up how your programs can generate insightful statistical analyses and visualizations.

But my point is: having a hard time with math is not an excuse to avoid programming. You'll find that as you become a useful programmer, the incentives to learn math as needed will come naturally.

This chapter introduces Ruby's basic number classes and arithmetic operations.

Number classes

There are two types of numbers that you'll deal with regularly:

You probably know this as an integer. A whole number with no decimal point, e.g. 42
This is basically a decimal number, e.g: 42.923812

You'll find that every data type in Ruby has a class: a set of defined properties and functionality.

What does it matter that there is a class for integers (Fixnum) and a class for decimal numbers (Float)? As we start out, not much. You can do arithmetic with either type of number:

9 + 6
#=> 15
3.141 + 0.00059
#=> 3.14159

Note: If the decimal number doesn't have a whole component – i.e. it's between 1.0 and -1.0, you need to lead the decimal point with a 0. So use, for example, 0.5, as Ruby won't accept .5

Or with both Float and Fixnum together:

1 + 0.618
#=> 1.618



Ruby includes all the basic math operators:

(to the) power

The modulo operator is probably the one most unfamiliar to non-programmers. It finds the remainder of a when divided by b:

16 / 5   #=> 3
16 % 5    #=> 1

Note that the division expression 16/5 does not return 3.2. Because you are only working with integers (i.e. Fixnums), Ruby will return an integer with the decimal part cut off.

If you want a decimal number, you'll have to include a decimal number in the mix:

16 / 5   #=> 3            
16 / 5.0   #=> 3.2
16.0 % 5   #=> 3.2
16 % 5.0 #=> 1.0

Number methods

Methods are how Ruby objects – everything in Ruby is an "object", including numbers – just "do things." All of the arithmetic operators are methods, so think of the plus sign + as the method to add two numbers together.

We will cover the concept of methods in its own chapter. For now, think of methods as commands, a kind of shortcut for Ruby objects to "do something."

For example, both the Float and Fixnum classes have a method named abs, which is short for "absolute value." If you've forgotten the term, the absolute value of a number is its numerical value regardless of whether it is positive or negative.

We invoke an object's method by using the dot character: .

-106.abs   #=>    106
78.abs   #=>    78      
Converting number types

If you want to convert a number to another type of number, Ruby provides two methods: to_i and to_f, which converts a number to an integer and float, respectively:

16 / 5.to_f   #=> 3.2      
16 / 5.0.to_i   #=> 3

(16.0 / 5.0).to_i   #=> 3

(16.0.to_i / 3.0.to_i).to_f   #=> 5.0   

Ruby can determine that the dot between two numbers – 42.3 – is meant to be a decimal point. Likewise, a dot between a number and a word is meant to be the dot that invokes the number's method, such as 42.3.to_i.

Let's take a closer look at the last expression of the previous example:

(16.0.to_i / 3.0.to_i).to_f   #=>   5.0

Both operands in the division operation end up being integers. If the to_f method hadn't been invoked, then the expression's value would be an integer:

(16.0.to_i / 3.0.to_i)   #=>   5
Exercise: Math practice

Let's review the numbers lesson and how to run Ruby code. Either open up irb or your code editor (TextWrangler, SciTE, etc.) to type in code.

Take a look at the following mathematical expressions and predict their output in Ruby. Then enter them into the Ruby environment to see the answers.

Knowing how to do this math in your head isn't important to programming. What is important is being able to recognize the operators at a glance and to understand why either a decimal or integer is returned as an answer.

12 - 1 * 4
-40 * -20
4.2.to_i * 5
10 + 1.to_f
14 % 4
1 % 100
6 % 3
3 ** 8 / 4.to_f
3 ** 8 / 4.to_i
(3 ** 8 / 4.to_i).to_f
20.9.to_i / 15 % 3            

12 - 1 * 4   #=> 8
-40 * -20   #=> 800
4.2.to_i * 5   #=> 20
10 + 1.to_f   #=> 11.0
14 % 4   #=> 2
1 % 100   #=> 1
6 % 3   #=> 0
3 ** 8 / 4.to_f   #=> 1640.25
3 ** 8 / 4.to_i   #=> 1640
(3 ** 8 / 4.to_i).to_f   #=> 1640.0
20.9.to_i / 15 % 3   #=> 1
Just numbers

This chapter is short because there's not much more to numbers. In fact, this is as complicated as numbers will get unless you plan to delve into statistics or the use of very large numbers.

It's more important that you get used to the idea that objects in Ruby each have a class with specific properties and methods. The next chapter deals with the String – the class that can hold non-number characters – and you'll see that the String class doesn't mix easy with the number classes.

So once again: Math is not a pre-requisite for programming.