The number hierarchy provides a common protocol for many numeric types. Smalltalk automatically converts between internal representations and provides unlimited precision integer arithmetic.

The most useful numeric classes are:

- Number - general Numbers
- Integer - integer Numbers
- Fraction- (arbitrary precision) rational numbers
- FixedPoint- decimal numbers
- Float - floating point (limited precision rational) numbers
- Others

Smalltalk's numeric classes make good use of polymorphism in the language:
instances of all numeric classes may be used interchangable in most
operations (for some, such as bit operations, it does not make sense).

Also, results of arithmetic (and other) operations are converted as
appropriate.

For example, executing:

```
1 / 3
```

(send the message `Fraction`

.
Protocol common to all numbers is:

- arithmetic:
`result`:=`number1`+`number2``result`:=`number1`-`number2``result`:=`number1`*`number2``result`:=`number1`/`number2``result`:=`number1`//`number2``(truncate result)``result`:=`number1`\`number2``(remainder)``result`:=`number1`\\`number2``(integer remainder)``result`:=`number`negated`result`:=`number`abs`result`:=`number`sign - misc:
`result`:=`number`sqrt`(square root)``result`:=`number`cbrt`(cubic root)``result`:=`number`truncated`(truncate towards zero)``result`:=`number`floor`(truncate towards negative infinity)``result`:=`number`ceiling`(truncate towards positive infinity)``result`:=`number`rounded`(round to nearest integer)``result`:=`number`roundTo:`number2``(round to nearest multiple of number2)``result`:=`number`factorial`result`:=`integer1`gcd:`integer2``(greatest common divisor)``result`:=`integer1`lcm:`integer2``(least common multiple)``result`:=`number1`min:`number2``(minimum of two numbers)``result`:=`number1`max:`number2` - testing:
`boolResult`:=`number`negative`boolResult`:=`number`even`boolResult`:=`number`odd`boolResult`:=`number1`=`number2``(same value)``boolResult`:=`number1`~=`number2``(not same value)``boolResult`:=`number1`>`number2``(also: >=, < and <=)``boolResult`:=`aNumber`between:`lowBounds`and:`highBounds` - trigonometric & math functions:
`result`:=`number`sin`result`:=`number`cos`result`:=`number`arcSin (`many other trigonometric operations`)`result`:=`number`exp`result`:=`number`ln`result`:=`number`raisedTo:`number2` - bit operations (integers only):
`result`:=`integer1`bitAnd:`integer2``result`:=`integer1`bitOr:`integer2``result`:=`integer1`bitShift:`count``result`:=`integer1`bitXor:`integer2``result`:=`integer1`lowBit - converting:
`aNumber`:= Number readFrom:`aStringOrStream`onError:`replacementValue``aNumber`:= Number readFrom:`aStringOrStream``anInteger`:= Integer readFrom:`aStringOrStream``aString`:=`aNumber`printString`aString`:=`anInteger`printStringRadix:`radixInteger``aFloat`:=`aNumber`asFloat`anInteger`:=`aNumber`asInteger`aFraction`:=`aNumber`asFraction`aFixedPoint`:=`aNumber`asFixedPoint:`numDecimals`

More details are found in the
"`Number`

class documentation".

`Integer`

itself, but instead
of one of its subclasses, `SmallInteger`

or `LargeInteger`

.
`SmallInteger`

represents integers which fit into one machine word.Storage of smallIntegers is very space efficient: in contrast to all other objects, smallIntegers are technically not represented by a pointer to the object, but instead the value is encoded in the pointer itself. Since one bit is required to distinguish smallIntegers from object references, one bit is lost for the storage of the integers value. Therefore, the smallInteger range is typically the 32bit range (on a 32bit machine), limiting the possible values to -2^30 to 2^30-1 (*).

`LargeInteger`

represents integers which are out of the valid smallInteger range. They can represent arbitrary values (i.e. beside memory limitations, the valid range of largeIntegers is not limited).

In addition to the above listed generic protocol for all numbers, integers respond to a number of additional messages for bitwise access, factorial and fibonacci computations, hex digit extraction etc.

More details are found in
"`Integer's`

class documentation", in
"`SmallInteger's`

class documentation" and in
"`LargeInteger's`

class documentation".

(1 / 3) * 3 = 1

while the corresponding float operation:
(1 / 33) asFloat * 33

may return 0.999999... on some systems due to rounding errors.
Fractional results from arithmetic operations are automatically reduced; therefore,

```
(1 / 3) * (1 / 3) * 3
```

gives a result of `1/3`

(not 3/9).
Beside memory limitations, the precision of fractional numbers is unlimited. A fractional resulting from an arithmetic operation is always reduced by finding the greatest common divisor of the numerator and denominator. Therefore, you will never get a fractional result like "(2 / 6)".

More details are found in the
"`Fraction`

class documentation".

FixedPoint numbers are the right choice if you have to deal with money and other entities where rounding errors are to be avoided.

As a special form of fraction, fixedpoint numbers respond to the usual arithmetic protocol. Any other number can be converted to a fixedpoint via:

- converting:
`aFixedPoint`:=`aNumber`asFixedPoint:`numDecimals`

More details are found in the
"`FixedPoint`

class documentation".

`double`

implementation.
On most modern systems, the IEEC representation is used (but be careful on OpenVMS and IBM mainframe systems...).

Typically, floats are represented in 64bits and the precision of the mantissa is 53bits
(i.e. some 15 decimal digits)
- but you should not depend on this being true on all hardware architectures.
Consult your CPU and/or C-compiler's documentation of your actual system for more information.

Two companion classes called `ShortFloat`

and `LongFloat`

are also available, which correspond to the C-compiler's `float`

and `long double`

implementations.
Typically `ShortFloat`

uses a 32 bit representation (i.e. roughly 6 decimal digits),
while `LongFloat`

uses an 80bit or 128 bit representation (i.e. roughly 19 digits).

Be aware, that not all C-compilers support the `long double`

type;
on those systems, `LongFloats`

are mapped to regular doubles with 64 bits.

Due to historic reasons, the existing Smalltalk systems used different precision and/or names for their float number classes:

- the original ST-80 provided a single
`Float`

class, which represented 32bit float numbers (IEEE single precision). -
ObjectWorks added a
`Double`

class, providing a 64bit representation (IEEE double precision). -
in contrast, ST/V's and
`VisualAge`

provide 64bits in their`Float`

class (IEEE double precision).

`Float`

" class uses double (64bit) precision,
and ST/X defines "`Double`

" as an alias for it.
Thus both "`Double`

" and "`Float`

" refer to the same 64bit floating point class.
If you explicitly want only 32bit of precision, you have to use instances of "`ShortFloat`

".
Since having more precision does usually no harm to the program,
this choice should ease porting of Smalltalk code from any system.
However, be aware of the fact that a float in ST/X takes up
more memory than a float in ST-80 (which should not be a problem, these days).
Late news:

Abiously, the ANSI standardization team also recgnized those difficulties and
defined aliases for those 3 classes: "`FloatE`

", "`FloatD`

" and "`FloatQ`

" are alieases to
the single precision, double precision and long precision float classes respectively.

Thus, if you have to ensure a particular precision, either refer to one those classes
explicitly, or convert your numbers using one of: "`asFloatE`

", "`asFloatD`

" or "`asFloatQ`

".

A warning:

many beginners (and as real world examples show) also some non-beginners seem to forget that
floating point numbers are only approximations to a real number, and suffer from errors due to non-representability and from rounding.

- non-representability

because floating point numbers are represented as a sum of powers-of-two, many numbers lead to endless repeating binary digit sequences. For example, the number "1/10" (i.e. 0.1) cannot be represented as a sum of powers of two (b1*1/2) + b2*1/4 + b3*1/8) +....

Thus, there will always be an error in the last bit and the actual value of the corresponding float will be some "0.09999999..x".The printing functions will "compensate" for this, by rounding on the last digit and "faking" an exact value most of the time.

However, when such a number is used in a computation, these last-bit errors may accumulate to an error larger than one least-significant bit, and will then no longer be "faked" away by the print function.

Try adding up 0.1 one hundred times (i.e. "`(Array new:100 withAll:0.1) sum`

"), which results in "9.99999999999998..." - precision-errors
when adding two numbers, bits of the smaller number will be lost, if their quotient
is larger than the precision number of bits.
Consider adding 1e15 (i.e. 1000000000000000.0) plus 1.0, resulting in 1000000000000001.0.
this still fits the 64bit (which have 53 bits of precision in the mantissa)
and is therefore still representable as double float.

try: "1e15 + 1 - 1e15", which results in 1.0"Now try the same with 1e16; you'll find that: "1e16 + 1 - 1e16", results in 0.0, which is definitely incorrect. The reason is that 1e16 requires ld(1e16) (=53.15) bits of precision, which is right above the number of bits we have in a double's mantissa.

For these reasons:
**Never use floats when exact results are needed - especially when computing monetary values! **

More details are found in
"`Float's`

class documentation"
,
"`ShortFloat's`

class documentation".
and in
"`LongFloat's`

class documentation".

you may also take a look at the experimental
"`QDouble`

".
class, which provides roughly four times the precision, but being much slower in computations.

All of these classes inherit from
"`LimitedPrecisionReal`

".

You can also extent the Number hierarchy, by adding new classes which
implement a certain minimum protocol (they should know how to perform
some of the basic arithmetic operations, and how to be converted into
other representations).

As an example and guideline on how this is done, have a look at the implementation of the
`Complex`

number class.

Notes:

(*)

One bit is lost for implementation reasons. Therefore, the number of bits in a smallInteger is the machine's native integer size minus one; usually 31 (63 on a 64bit architecture like the DEC-alpha or x86_64).

( for details, see object representation)

Copyright © 1996 Claus Gittinger Development & Consulting

Doc $Revision: 1.33 $ $Date: 2017/06/22 14:53:04 $