# 8.2: Numbers


Remarkably, numbers in Smalltalk are not primitive data values but true objects. Of course numbers are implemented efficiently in the virtual machine, but the Number hierarchy is as perfectly accessible and extensible as any other portion of the Smalltalk class hierarchy.

Numbers are found in the Kernel-Numbers category. The abstract root of this hierarchy is Magnitude, which represents all kinds of classes supporting comparision operators. Number adds various arithmetic and other operators as mostly abstract methods. Float and Fraction represent, respectively, floating point numbers and fractional values. Integer is also abstract, thus distinguishing between subclasses SmallInteger, LargePositiveInteger and LargeNegativeInteger. For the most part users do not need to be aware of the difference between the three Integer classes, as values are automatically converted as needed.

## Magnitude

Magnitude is the parent not only of the Number classes, but also of other classes supporting comparison operations, such as Character, Duration and Timespan. (Complex numbers are not comparable, and so do not inherit from Number.)

Methods < and = are abstract. The remaining operators are generically defined. For example:

Code $$\PageIndex{1}$$ (Squeak): Abstract Comparison Methods

Magnitude» < aMagnitude
↑self subclassResponsibility

Magnitude» > aMagnitude
↑aMagnitude < self


## Number

Similarly, Number defines +, --, * and / to be abstract, but all other arithmetic operators are generically defined.

All Number objects support various converting operators, such as asFloat and asInteger. There are also numerous shortcut constructor methods, such as i, which converts a Number to an instance of Complex with a zero real component, and others which generate Durations, such as hour, day and week.

Numbers directly support common math functions such as sin, log, raiseTo:, squared, sqrt and so on.

Number»printOn: is implemented in terms of the abstract method Number»printOn:base:. (The default base is 10.)

Testing methods include even, odd, positive and negative. Unsurprisingly Number overrides isNumber. More interesting, isInfinite is defined to return false.

Truncation methods include floor, ceiling, integerPart, fractionPart and so on.

1+2.5        →    3.5        "Addition of two numbers"
3.4*5        →    17.0       "Multiplication of two numbers"
8/2          →    4          "Division of two numbers"
10 - 8.3     →    1.7        "Subtraction of two numbers"
12 = 11      →    false      "Equality between two numbers"
12 ∼= 11     →    true       "Test if two numbers are different"
12 > 9       →    true       "Greater than"
12 >= 10     →    true       "Greater or equal than"
12 < 10      →    false      "Smaller than"
100@10       →    100@10     "Point creation"


The following example works surprisingly well in Smalltalk:

1000 factorial / 999 factorial    →    1000


Note that 1000 factorial is really calculated which in many other languages can be quite difficult to compute. This is an excellent example of automatic coercion and exact handling of a number.

$$\bigstar$$ Try to display the result of 1000 factorial. It takes more time to display it than to calculate it!

## Float

Float implements the abstract Number methods for floating point numbers.

More interestingly, Float class (i.e., the class-side of Float) provides methods to return the following constants: e, infinity, nan and pi.

Float pi                        →    3.141592653589793
Float infinity                  →    Infinity
Float infinity isInfinite       →    true


## Fraction

Fractions are represented by instance variables for the numerator and denominator, which should be Integers. Fractions are normally created by Integer division (rather than using the constructor method Fraction»numerator:denominator:):

6/8            →    (3/4)
(6/8) class    →    Fraction


Multiplying a Fraction by an Integer or another Fraction may yield an Integer:

6/8*4    →    3


## Integer

Integer is the abstract parent of three concrete integer implementations. In addition to providing concrete implementations of many abstract Number methods, it also adds a few methods specific to integers, such as factorial, atRandom, isPrime, gcd: and many others.

SmallInteger is special in that its instances are represented compactly — instead of being stored as a reference, a SmallInteger is represented directly using the bits that would otherwise be used to hold a reference. The first bit of an object reference indicates whether the object is a SmallInteger or not.

The class methods minVal and maxVal tell us the range of a SmallInteger:

SmallInteger maxVal = ((2 raisedTo: 30) - 1)        →    true
SmallInteger minVal = (2 raisedTo: 30) negated      →    true


When a SmallInteger goes out of this range, it is automatically converted to a LargePositiveInteger or a LargeNegativeInteger, as needed:

(SmallInteger maxVal + 1) class    →    LargePositiveInteger
(SmallInteger minVal - 1) class    →    LargeNegativeInteger


Large integers are similarly converted back to small integers when appropriate.

As in most programming languages, integers can be useful for specifying iterative behaviour. There is a dedicated method timesRepeat: for evaluating a block repeatedly. We have already seen a similar example in Chapter 3:

n := 2.
3 timesRepeat: [ n := n*n ].
n    →    256


This page titled 8.2: Numbers is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Andrew P. Black, Stéphane Ducasse, Oscar Nierstrasz, Damien Pollet via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.