Number API Functions

Aus expecco Wiki (Version 2.x)
Zur Navigation springen Zur Suche springen

This document lists most useful (and most often needed) functions. Be aware, that there are many more to be found in either the class references or via the builtin class browser.

See also "Numbers" in Expecco_API.
Reference: Integer, Float, Fraction, ScaledDecimal, Complex which all inherit from Number

Back to Useful API Functions

Literals (i.e. Constant Numbers)[Bearbeiten]

Literals are constants as written in elementary Smalltalk code and also given as freeze value to a pin or initial value to a variable.

Integer Literals[Bearbeiten]
1234 
1234567890123456789012345678901234567890
-123456789012345678901234567890
0xaffe or 16rFFAA (hex in C/JSON or Smalltalk syntax)
-0xaffe or 16r-FFAA (negative hex in C- or Smalltalk syntax)
0b101010 or 2r0101 (binary in C/JSON or Smalltalk syntax)
0o377 or 8r377 (octal)
<N>rXXX (arbitrary radix N)

Integer constant; decimal, hex, binary, octal or any base N;
integers may be arbitrary long

Floating Point Literals (Limited Precision Rationals)[Bearbeiten]
0.5
1e5
-1.2e-3
12.6789q or 1.7e-21q (extended precision)
3.6789f or 2.67e5f (single precision)

Float constant; actually IEEE double precision;
use "q" instead of "e" for extra precision (extended IEEE floats) or "f" for single/less precision.

In addition to single, double and extended floats, additional precision representations are available (see below).

Fraction Literals[Bearbeiten]
(4/3)
(523423432/3)
(-5/3)

Fraction constants (numerator / denominator); these are exact

Scaled Decimal Literals[Bearbeiten]
123.456s2
-33.4s2
100s2

Scaled decimal; the number after the "s" defines the print-scale. The above numbers print themself rounded to 2 fractional digits e.g. "123.46", "-33.40" or "100.00" (although internally, the full precision is kept for further operations).

Complex Number Literals[Bearbeiten]
(4+3i) or (-5+2i) or (-10-4i)
(4.3+3.1i) or (4.3 + 1i) 
5.0 i or 5i

Complex number (real part / imaginary part)

Wellknown Constant Numbers[Bearbeiten]

A few common constants are known by name. They are answered by corresponding getter messages sent to the number class of which you want the constant (i.e. these return the constants in their respective precision):

Float pi
pi as IEEE double precision number
FloatD pi
Float64 pi
the same as above (FloatD and Float64 are aliases for the default float class "Float")
FloatQ pi
Float80 pi
pi as IEEE extended precision number (FloatQ and Float80 are aliases for the extended float class also known as "LongFloat")
FloatE pi
Float32 pi
pi as IEEE extended precision number (FloatE and Float32 are aliases for the single precision float class also known as "ShortFloat")
<FloatClass> ln2
<FloatClass> ln10
<FloatClass> sqrt2
<FloatClass> sqrt3
<FloatClass> e
<FloatClass> NaN, infinity and negativeInfinity

Take a look at the class in a class browser for additional useful constants.

Float Representations[Bearbeiten]

Standard Float Representations[Bearbeiten]

For traditional reasons, the name "Float" refers to IEEE double precision floating point numbers in expecco, whereas IEEE single precision floats are called "ShortFloats". For more readability, the float classes can also be referred to via their aliases:

Float32 = FloatE (=ShortFloat),
Float64 = FloatD (=Float)
Float80 = FloatQ (=LongFloat).

There is usually no need to explicitly use or refer to ShortFloats (or FloatEs): modern CPUs usually process them as fast as doubles.
However, you may need them to either simulate single precision arithmetic (which may show different convergence behavior in some series computations) or to exchange binary data with other systems (i.e. to generate a byteArray containing the float's bits or to write a single precision float's bits to a stream).

Float / FloatD / Float64[Bearbeiten]

Floats (double precision IEEE floats) are stored in 64 bits, having an 11-bit exponent and a 52+1 bit mantissa (1 bit is hidden due to normalization).
This gives roughly 15 digits of precision.
This is the default used, if you write a float number in the code.

ShortFloat / FloatE / Float32[Bearbeiten]

ShortFloats (single precision IEEE floats) are stored in 32 bits, having an 8-bit exponent and a 23+1 bit mantissa (1 bit is hidden due to normalization).
This gives roughly 7 digits of precision.

LongFloat / FloatQ / Float80[Bearbeiten]

LongFloats (extended precision IEEE floats) are stored in 80 bits, having a 15-bit exponent and a 64 bit mantissa.
This gives roughly 19 digits of precision.


By Default, Floats print themself with either a decimal point or an exponent indicator 'e', e.g. "0.5", "10.0" or "1.3e3". However, there are a number of functions provided to print numbers in other formats.

Experimental Extra Float Representations[Bearbeiten]

For background information on why you should not trust IEEE floating point arithmetic, and why you may need more precision in some situations, please read the article "Do not trust Floating Point".

Expecco includes experimental versions for higher precision floats. Please do not use them for production code. They are considered being "work in progress", and may or may not work as expected. Especially trigonometric and other math functions are known to be erroneous or generate less precise results as expected. Please use those with extra care and report bugs.

For now, we recommend the use of LargeFloat instead of QuadFloat/OctaFloat or QDouble if large precision is needed.

LargeFloat[Bearbeiten]

LargeFloats use an arbitrary (configurable) number of bits to represent floats with any precision.
They are completely software emulated, which makes most operations much slower than with other floats. In other languages, these are sometimes called "BigFloat".

Usage is similar to QDoubles as described below. However, when creating aLargeFloat, you have to give the desired precision (in bits) as argument:

1.0 asLargeFloatPrecision:200

or in decimals:

1.0 asLargeFloatDecimalPrecision:100

If no precision is given, a default prcision of 200 bits is used, as e.g. by:

1.0 asLargeFloat

You will get roughly 1 decimal digit of precision per 3 bits (i.e. the above 200bit precision corresponds to a decimal precision of roughly 60 digits).

Example (1):

45 degrees sin
    => 0.707106781186547 
       (a float with roughly 15 digits precision)

(45 asLargeFloatPrecision:200) degrees sin
    => 0.70710678118654752440084436210484903928483593768847403658834

and back:
(45 asLargeFloatPrecision:200) degrees sin arcSin radiansToDegrees
   => 45.0

1) the meaning of "degrees" is described in the "Physical Values" document.

QDouble / FloatQD[Bearbeiten]

QDoubles use 4 double precision floats (holding the unevaluated sum of 4 doubles) to represent a float with roughly 200 bits of precision (actually often more, depending on the values).
QDoubles are able to represent sums/differences of a very large float with a very small float.
For example with regular floats (i.e. IEEE double precision):

(1e200 + 1e-15) - 1e200
    => 0.0

the small value is lost.
Whereas with QDoubles as in:

(1e200 asQDouble + 1e-15) - 1e200
    => 1e-15

it is preserved.

QDoubles are thus able to represent sums of wildly distant numbers. With regular floats, the following computations all deliver a wrong result:

1e200 + 1e-15 + 1e-100                              
    => 1E+200  (loosing 1e-15 + 1e-100)

(1e200 + 1e-15 + 1e-100) - 1e200             
    => 0       (wrong; lost 1e-15 + 1e-100)

(1e200 + 1e-15 + 1e-100) - 1e200 - 1e-15
    => -1e-15  (wrong)

(1e200 + 1e-15 + 1e-100) - 1e200 - 1e-100          
    => -1E-100 (wrong)

(1e200 + 1e-15 + 1e-100) - 1e200 - 1e-15 - 1e-100   
    => -1E-015 (wrong)

whereas with QDoubles, we get:

1e200 asQDouble + 1e-15 + 1e-100                              
    => 1E+200  (printed, actual value is correct)

(1e200 asQDouble + 1e-15 + 1e-100) - 1e200                    
    => 1.0e-15 (correct)

(1e200 asQDouble + 1e-15 + 1e-100) - 1e200 - 1e-15            
    => 1E-100  (correct)

(1e200 asQDouble + 1e-15 + 1e-100) - 1e200 - 1e-100           
    => 1E-015  (correct)

(1e200 asQDouble + 1e-15 + 1e-100) - 1e200 - 1e-15 - 1e-100   
    => 0.0     (correct)

or another example:

t := 1234 + 0.567890 + 0.00000012345 + 0.000000000006789.
a := t - 1234.              "/ 0.567890123456891     (mhmh ?) 
b := a - 0.567890.          "/ 1.23456891154561E-07  (mhmh ?) 
c := b - 0.00000012345.     "/ 6.89115456081139E-12  (mhmh ?)
d := c - 0.000000000006789. "/ 1.0215456081139E-13   (wrong)

whereas:

t := 1234 asQDouble + 0.567890 + 0.00000012345 + 0.000000000006789.
a := t - 1234.              "/ 0.56789012346    (mhmh ?)
b := a - 0.567890.          "/ 1.23456789e-7    (mhmh ?)
c := b - 0.00000012345.     "/ 6.789E-12        (correct) 
d := c - 0.000000000006789. "/ 0.0              (correct)

However, there is no insurance, that bits are not lost. If one of the operands already needs all four doubles (because it cannot be represented exactly as a sum of 3 floats), bits from the second operand may be lost. For example:

1e100 asQDouble + 1

will result in 1e100 (without the one), because 1e100 already uses all bits (i.e. all 4 doubles) of the QDouble. If you need the full precision, you may have to use LargeFloats, although the processing overhead may be larger then.

Due to the extra processing overhead, operations are slower than with doubles or extended doubles.

Attention:
Strange results seem to be generated when regular floats are converted to QDoubles iff the original float was not representable as an exact number. For example, adding the float 0.2 to the QDouble 1.0QD will result in a number different from 1.2QD, because the original 0.2 had an error in its last bit, which gets now visible when converted to QDouble.

Better use LargeFloat instead, if more precision is needed.

QuadFloat / Float128[Bearbeiten]

QuadFloats use the 128 bit IEEE quadruple precision binary128 format, with 15 exponent bits, providing roughly 34 digits of precision.
QuadFloats are software emulated, and thus computations are slower than with regular floats.

Attention:
Do not use Quadfloats for now, except to convert from/from binary data. Currently, they may not handle subnormals in some arithmetic operations correctly and may also return slightly incorrect results for trigonometric operations (rounding modes are not correctly implemented). Use LargeFloat if more precision is needed.
OctaFloat / Float256[Bearbeiten]

OctaFloats use the 256 bit IEEE octuple binary256 format, with 19 exponent bits, providing roughly 70 digits of precision.
OctaFloats are also software emulated by a flexible arbitrary precision IEEE algorithm, and slower than QuadFloats and QDoubles (actually often even slower than LargeFloats below).

Attention:
Do not use Octafloats for now, except to convert from/from binary data. Currently, they do not handle subnormals in some arithmetic operations correctly and may also return slightly incorrect results for trigonometric operations (rounding modes are not correctly implemented). Use LargeFloat if more precision is needed.

Fractions[Bearbeiten]

Fractions are returned from integer divisions; i.e. when both "a" and "b" are integers and "a / b" does not result in an integral result.
Fractions are exact; no precision is lost. Results of arithmetic operations are reduced and possibly yield integers. Thus:

(1/3) * (1/3)
     => (1/9)

and:

(1/3) * 9
     => 3 (an exact integer)

Fractions print themself as "(a / b)".
They are computed in software and thus usually slower than float operations (especially with huge numerators/denominators).

Scaled Decimals[Bearbeiten]

These print themself rounded to a specified number of fractional digits (the so called scale).
For example, "1234.567 asScaledDecimal:2" will print itself as "1234.57" (i.e. rounded).
However, internally the full precision is kept so an arithmetic operation will still deliver a correct result.

Scaled decimals are perfect to present values to a user or in a report in a "human friendly" rounded format.
Example:

a := 1234.567 asScaledDecimal:2.
a print.  
    => '1234.57'

b := 23.007 asScaledDecimal:2
b print.  
    => '23.01'

(a + b) print.
    => '1257.57'

This is because the sum (a+b) is actually (1234.567 + 23.007 = 1257.574), which is printed as '1257.57' (rounded).


This also works for Fractions:
Fraction example:

c := (1/3) asScaledDecimal:2.
c print.  
    => '0.33'

d := (2/3) asScaledDecimal:2
d print.  
    => '0.67'

(c + d) print.
    => '1.00'

Be aware that the output will look strange (i.e. look wrong) if monetary values are presented this way, e.g. on an invoice's summation. Here, we'd expect a sum of amounts to be the sum of previously listed values (think of sales tax being computed, giving a rounded Cent-value).
See FixedDecimal below for a better solution.

ScaledDecimals can be rounded to their scale, so that further computation are taking that value. Thus taking the above values rounded:

a := a roundedToScale.
b := b roundedToScale.
(a + b) print.
    => '1257.58'

shows the correct value in a table.

You can also use "truncatedToScale", to continue arithmetic with the truncated value.

Fixed Decimals[Bearbeiten]

(new with expecco 21.2)
Similar to ScaledDecimals; however, these do NOT hold the correct result, but instead always round to the specified scale and thus the value used for further operations is the (rounded) value printed.
Arithmetic operations will deliver a rounded result. Fixed decimals are good to represent money, especially when computing and printing sums of monetary values e.g. in an invoice.
Example:

a := 1234.567 asFixedDecimal:2.
a print.  
    => '1234.57'

b := 23.007 asFixedDecimal:2
b print.  
    => '23.01'

(a + b) print.
    => '1257.58'

This looks correct to a human, as the values sum up correctly.

Be aware that converting a float to a FixedDecimal and back will not necessarily return the starting number. Unlike ScaledDecimals, FixedDecimals do NOT preserve the original value.

If you have a pre 21.2 version, the FixedDecimal behavior can be "simulated" by forcing a ScaledDecimal to round its value to the shown scale (as described above).

Number Ranges[Bearbeiten]

These behave like collections (see there) and are typically created by one of the following:

(start to: stop)
(start to: stop by: step)

For example:

(1 to:10) do:[:i |
  Transcript showCR: e'{i} squared is {i squared}'.
]

Complex Numbers[Bearbeiten]

Are created as constants "(a + b i)" or created with "Complex real:a imaginary:b".
An imaginary is created with the "i" message (e.g. "5 i" yields (0 + 5 i).
Complex numbers print themself as "(a + b i)".

Complex results can also be returned from e.g. the square root operator (sqrt) and logarithm operations (log, ln) IFF imaginary results are trapped (which means that an exception handler for the ImaginaryResult notification is present and proceeds the exception).
The convenient helper "trapImaginary:" does that for you:

-4 sqrt

will report an error, whereas:

Number trapImaginary:[ -4 sqrt ]

will return a complex result.

If imaginary results are not trapped, square root and log operators will signal an exception instead.

Measurement Values[Bearbeiten]

These hold an error percentage in addition to the actual value. These are useful to track upper and lower bounds of a measured or estimated value. Arithmetic operations will keep this error in the result.
They can be constructed from any number via the "±" or "±%" binary operators:

(aNumber ± errRange)
a measurement value with ± an absolute error of errRange.
(aNumber ±% percentage)
a measurement value with a relative error of percentage.

For example,
"(50 ± 3)" represents a measurement value with 6% accuracy (i.e. the actual value is somewhere in the interval [50-3 .. 50+3]), and
"(100 ±% 3)" represents a measurement value with 3% accuracy (i.e. the value is in [100-3 .. 100+3]).

Measurement values are not real numbers, but can in most operations be treated like one (i.e. the usual arithmetic operations are supported).

Physical Values[Bearbeiten]

These hold a number or measurement value in addition to a unit (e.g. meter, kilogram, volt, ampere, etc.). They are documented in depth in a separate part of this wiki. Physical values are created via unit operators.
For example, "50 volt" represents a voltage value of 50 volts.
Physical values are not numbers, but can in most parts be treated like one (i.e. most arithmetic operations are supported).

100 volt * 3

yields "300 V". And:

100 volt * 0.1 ampere

yields "10 W" (watt). And:

10 volt / 2 ampere

yields "5 ohm".

Physical values can also be combined with measurement values:

100 volt ±% 3

represents a measured voltage with 3% possible error (i.e. "(100 ± 3) V").
And:

10 volt ± 2 volt

represents a measured voltage with 20% error (i.e. value in [8 .. 12] V")

See details in the "Physical Values" document.

Operations with Mixed Types[Bearbeiten]

Normally, there is no need for explicit conversion between number types. The result of mixed operations is computed with the type of the operand which has the higher "generality". This conversion is called "coercion" - i.e. the operand with the lower generality is coerced into the type of the other before the operation is performed.

The order of generalities is:

Integer < Fraction < ScaledDecimal < FixedDecimal 
   < Float32 < Float64 < Float80 < Float128 < Float256 < LargeFloat < Complex

Thus, when a calculation involves both an integer and a fraction, the result will be a fraction (unless the result can be reduced to an integer).
When an operation involves a float and an integer or fraction, the result will be a float.
When either one is a complex, the result will also be.

When two floats are involved, the result will be generated with the higher precision.

But you should not be fooled by that: we do not get previously lost bits back, when a lower precision float is converted to a higher precision; the missing bits are simply assumed to be zero. In other words: "ShortFloat pi asFloat" will still only have roughly 7 digits of precision (which the original short float had), whereas "Float pi" will have its 15 digits.

Mixed Operations with MeasurementValues[Bearbeiten]

Automatic conversion is also performed when MeasurementValues are involved:

aMeasurementValue + aNumber => MeasurementValue
aMeasurementValue - aNumber => MeasurementValue
the result will have the same error as the receiver.
E.g. (10 ± 1) + 10 => (20 ± 1).

 

aMeasurementValue * aNumber => MeasurementValue
aMeasurementValue / aNumber => MeasurementValue
the error will also be scaled by aNumber.
E.g. (10 ± 1) * 10 => (100 ± 10).

 

Mixed Operations with PhysicalValues[Bearbeiten]

PhysicalValues can be scaled by a scalar or multiplied by another physical value (possibly resulting in a value with a different unit). Addition and subtraction are only allowed if the arguments have the same base type:

aPhysicalValue + aNumber => error
aPhysicalValue - aNumber => error
not allowed

 

aPhysicalValue * aNumber => PhysicalValue
aPhysicalValue / aNumber => PhysicalValue
for example, 10 volt * 10 => 100 volt,
and 10 volt / 1000 => 10 milliVolt

 

Most Common/Useful Operations[Bearbeiten]

Testing[Bearbeiten]

aNumber isNaN => Boolean
aNumber.isNaN() (in JS syntax)
Check if number is NaN ("Not a Number"). Notice that there are multiple representations of "NaN": "Float32 NaN", "Float64 NaN" etc.
Therefore, you should not compare against NaN with an identity compare operations (i.e. you should use isNaN to test, not compare for identity against another NaN)

 

aNumber isFinite => Boolean
Check if number is not infinity and not NaN. As with NaN, there are multiple such "infinities"; one in each float class.

 

aNumber isInfinite => Boolean
Check if number is either positive infinity (INF) or negative infinity (-INF).

 

aNumber isPositiveInfinity => Boolean
Check if number is the positive infinity (+INF).

 

aNumber isNegativeInfinity => Boolean
Check if number is the negative infinity (-INF).

 

aNumber isInteger => Boolean
Check if number is an integral number.

 

aNumber isFraction => Boolean
Check if number is a fractional number.

 

aNumber isFloat => Boolean
Check if number is any float number (Float32, Float64, Float128, etc.).

 

aNumber exponent => Integer
For floats only: returns the exponent, such that the number's value is:
"mantissa * (2 ^ exponent)".

 

aNumber mantissa => Integer
For floats only: returns the mantissa, such that the number's value is:
"mantissa * (2 ^ exponent)".

 

aNumber precision => Integer
For floats only: returns the number of bits in the number's mantissa.

 

aNumber decimalPrecision => Integer
For floats only: returns the number of digits in the number's mantissa.

 

floatClass fmin => float
For float classes only: returns the smallest representable (normalized) number of that class.
For example, "FloatD fmin" would return 2.2250738585072e-308. Any operation which would generate a smaller number will deliver -INF.

 

floatClass fmax => float
For float classes only: returns the largest representable number of that class.
For example, "FloatD fmax" would return 1.79769313486232e+308. Any operation which would generate a larger number will deliver +INF.

 

floatClass emin / emax => integer
For float classes only: returns the smallest and largest possible exponent representable by numbers of that class.
For example, "FloatD emin" would return -1022. Notice that this is the exponent of the power-of-two; the corresponding decimal min/max exponent can be computed by multiplying it by log10(2).

 

aNumber isComplex => Boolean
Check if number is a complex number.

 

aNumber negative => Boolean
same as aNumber < 0

 

aNumber positive => Boolean
same as aNumber >= 0

 

aNumber strictlyPositive => Boolean
same as aNumber > 0

 

anInteger isPrime => Boolean
true if the number is a prime number

 

anInteger isPowerOf2 => Boolean
true if there exists an n, such that 2ˆn equals the number

 

anInteger isPowerOf: b => Boolean
true if there exists an n, such that bˆn equals the number

 

Arithmetic[Bearbeiten]

aNumber + aNumber => Number
aNumber - aNumber => Number
aNumber * aNumber => Number
aNumber / aNumber => Number
The usual arithmetic operators.
All of the above allow operands of any number type, and will generate a result as appropriate. When dividing integers, an exact result is returned (either integer or fraction). If any of the arguments is inexact (i.e. a floating point number), the result will be inexact. If both are exact, the result will be exact. Fractional results are reduced to the greatest common divisor as denominator.
Point right.png Notice, that Smalltalk evaluates them left to right, without special precedences.
Thus you should always use parentheses to group expressions when there are two or more operators in an arithmetic expression. It is good practice to use parentheses even in expressions where the evaluation order gives the correct result.

 

aNumber ** aNumber => Number
aNumber raisedTo: aNumber => Number
exponentiation (raising to a power)
Examples:
 2 ** 20
     => 1048576
 4 ** 3.5
     => 128.0
 100 ** 0.5
     => 10.0

 

aNumber // aNumber => Integer
aNumber \\ aNumber => Integer
Truncated result and remainder (towards the next smaller integer i.e. towards negative infinity).
The following equation holds: (a // b) * b + (a \\ b) = a
Examples:
 100 // 3
     => 33
 100 \\ 3
     => 1
 -100 // 3
     => -34
 -100 \\ 3
     => 2

 

aNumber quo: aNumber => Integer
aNumber rem: aNumber => Integer
Truncated result (towards zero) and corresponding remainder.
For positive arguments, this is the same as the above, for negative args, a different result is returned.
However, the equation is similar to above: (a quo: b) * b + (a rem: b) = a
Examples:
 100 quo: 3
     => 33
 100 rem: 3
     => 1
 -100 quo: 3
     => -33
 -100 rem: 3
     => -1

 

aNumber abs => Number
the absolute value.
aNumber negated => Number
the negated value.

Mathematical and Trigonometric Functions[Bearbeiten]

The usual operations are provided as unary messages to the number:

aNumber ln => Number
aNumber log10 => Number
aNumber log2 => Number
aNumber log: base => Number
aNumber integerLog10 => Integer
aNumber integerLog2 => Integer
logarithm (natural, base10, base2 or arbitrary base).
These are not restricted to floats; they can also be applied to big integers,
as in: "1000 factorial ln".
By default, an error is reported for negative numbers;
to get a complex result, use "Complex trapImaginary:[ aNumber ln ]".

 

aNumber sqrt => Number
anInteger integerSqrt => Integer
square root and truncated square root
By default, an error is reported for negative numbers;
to get a complex result, use "Complex trapImaginary:[ aNumber sqrt ]".

 

aNumber cbrt => Number
anInteger integerCbrt => Integer
cubic root and truncated cubic root.

 

aNumber nthRoot: n => Number
the nth root.
"n nthRoot:2" gives the same result as "sqrt"
and "n nthRoot:3" the same as the cubic root.

 

aNumber exp => Number
number1 raisedTo: number2 => Number
number1 ** number2 => Number
exponentiation; the "**" binary operator is an alias for "raisedTo:".

 

aNumber sin => Number
aNumber cos => Number
aNumber tan => Number
aNumber cot => Number (cotangent)
aNumber sec => Number (secant)
aNumber csc => Number (cosecant)
aNumber arcSin => Number
aNumber arcCos => Number
aNumber arcTan => Number
aNumber arcTan2: x => Number
trigonometric functions

 

aNumber sinh => Number
aNumber cosh => Number
aNumber tanh => Number
aNumber arSinh => Number
aNumber arCosh => Number
aNumber arTanh => Number
hyperbolic functions

Truncation and Rounding[Bearbeiten]

aNumber ceiling => Number
returns the next larger integer (unless aNumber is integral).
E.g. truncates towards positive infinity.
aNumber floor => Number
returns the next smaller integer (unless aNumber is integral).
E.g. truncates towards negative infinity.
aNumber truncated => Integer
truncates towards zero
aNumber truncateTo: grid => Number
truncates towards the nearest multiple of grid.
E.g. "1.284 truncateTo:0.1" yields "1.2".
aNumber rounded => Number
rounds up/down towards the nearest integer
aNumber roundTo: grid => Number
rounds up/down towards the nearest multiple of grid.
E.g. "1.284 roundTo:0.1" yields "1.3" and "523 roundTo:5" yields "525".
aNumber roundToNumberOfDigits: n => Number
rounds up/down for n valid digits.
E.g. "1.284 roundToNumberOfDigits:2" yields "1.3" and "5234 roundToNumberOfDigits:2" yields "5200".
aNumber roundToPrecision: n => Number
rounds up/down for n decimal fraction digits.
E.g. "1.284 roundToPrecision:2" yields "1.28" and "5234.356 roundToPrecision:2" yields "5234.36".

Statistical / Combinatorical Functions[Bearbeiten]

anInteger factorial => Integer
the factorial; i.e. "n factorial" is 2*3*4...*n". Huge numbers are to be expected (try "1000 factorial inspect" in a workspace).
n binomialCoefficient: k => Integer
n binco: k => Integer
the binomial coefficient (aka. n over k or the number of ways of picking k unordered outcomes from n possibilities)
n agm: y => Float
the arithmetic-geometric mean

Other Special Functions[Bearbeiten]

integer1 gcd: integer2 => Integer
the greatest common divisor of integer1 and integer2.
integer1 lcm: integer2 => Integer
the least common multiple of integer1 and integer2.
anInteger fib => Integer
the nth Fibonacci number. Huge numbers are to be expected (try "1000 fib inspect" in a workspace).
aNumber fib_binet => Float
an approximation of the nth Fibonacci number according to Binet.
For example, "5000 fib_binet" gives: "1.0777734893072974780...e+10449" (by default with 200 bits precision)
aNumber erf => Float
the error function
aNumber gamma => Float
the gamma function
anInteger nextPrime => Integer
the next prime number.
anInteger primeFactors => Collection
the prime factors. Can take a long time for big numbers.

Bitwise Operators[Bearbeiten]

integer1 bitAnd: integer2 => Integer
integer1 bitOr: integer2 => Integer
integer1 bitXor: integer2 => Integer
bitwise and, or and exclusive or
integer1 bitShift: count => Integer
left shift if count is positive; right shift if negative
integer1 leftShift: count => Integer
left shift by count
integer1 rightShift: count => Integer
right shift by count
integer1 bitTest: integer2 => Boolean
integer2 is used as a mask (i.e. bitTest returns true if any bit in the mask is set in the left operand i.e. (i1 & i2) not equal 0
integer1 bitAt: bitNr => integer (0 or 1)
extract the nth bit, with bitNr starting at 1
integer1 lowBits: count => integer
extract count lowest bits
integer highBit => integer (1..)
the bit number of the highest bit, with bitNr starting at 1; zero if no bit is set
integer lowBit => integer (1..)
the bit number of the lowest bit, with bitNr starting at 1; zero if no bit is set

Printing[Bearbeiten]

Numbers can print themself on an output stream, or convert themself to a string:

aNumber printOn: aStream => void
aNumber printOn: aStream radix: base => void
aNumber printOn: aStream leftPaddedTo: length => void
aNumber printOn: aStream leftPaddedTo: length with: padCharacter => void
aNumber printOn: aStream paddedTo: length => void
aNumber printOn: aStream paddedTo: length with: padCharacter => void
aNumber printString => String
aNumber printStringRadix: base => String
aNumber printStringLeftPaddedTo: length => String
aNumber printStringLeftPaddedTo: length with: padCharacter => String
aNumber printStringPaddedTo: length => String
aNumber printStringPaddedTo: length with: padCharacter => String
The above generate a standard format, which should fit most needs. The padded variants fill with either space or the explicit padCharacter. The printOn: variants will send the string to an output stream; the printString variants will return the string.

 

formatString printf: { arg... } on: aStream => void
formatString printf: { arg... } => String
More fine control is available via the printf functions, which also offer a range of options to fill left or right, to control printing of the sign and to fill with zeros.
These two interpret the receiver as a C-printf-style format string, and an argument vector as first argument (use a brace-array constructor or pass a collection as argument).
Thus, multiple values are printed as in the following example:
'%04x %3d %+4.3f\n' printf:{ 123 . 4 . 3.14159 } on:Transcript
Individual conversions (to a string) can also be done with:
aNumber printfPrintString: formatString => String
Examples:
'% .4f' printf:{Float pi}         => ' 3.1416' (space after % ensures space for sign)
'% .4f' printf:{Float pi negated} => '-3.1416' (space after % ensures space for sign)
'%+.4f' printf:{Float pi}         => '+3.1416' ('+' after % enforces sign)
'%+.4f' printf:{Float pi negated} => '-3.1416' ('+' after % enforces sign)
Please refer to a C-printf manual page (e.g. https://en.wikipedia.org/wiki/Printf_format_string).
Notice that printf accepts C-style character escapes (which is not the case in general with Smalltalk string constants)

 

aNumber printRomanOn: aStream => void
roman style

Reading from Streams / Converting from Strings[Bearbeiten]

Numbers can be read from a stream or converted from a string. There are slight differences between them:

  • when reading from a stream of characters, the stream will be positioned after the number. So any non-digit character(s) after the number's characters will be returned by future read operations. The stream can be an internal or external (i.e. file-, pipe- or socket-) stream.
  • when converting from a string, no extra characters are expected/allowed after the number's digits, except for whitespace. Thus you'll usually get an error when trying to convert a string with garbage characters after the number (which is not the case when reading from a stream).

Therefore, if you want to read a number from a string which may have garbage characters after the digits, you should first create a read-stream on the string, and then read the number from the stream (i.e. use "Number readFrom:(someString readStream)" instead of "Number fromString:someString").

Numbers are read by sending the Number-class or one of its subclasses one of the "readFrom:" or "fromString:" messages.

If the class is the abstract class Number, then the read code will itself figure out, what kind of number to return. If the class is a concrete class (Float, Integer, Fraction etc.), you will get an instance of that class, unless the characters do not represent a valid number (of that class). In that case, an error is reported.

By default, errors are reported by raising an exception, unless you provide an error-handler as argument to the reader; more on that below.

Number readFrom: aStream => someNumber or error
this can return an instance of any of the number types
Number readFrom: aStream onError:[ errorValue ] => someNumber or errorValue
errorValue can be a constant, an arbitrary Smalltalk expression or even show a warn dialog or do whatever you like. In case of an error, the value returned from the read method will be the value provided by the error-block. Notice, that numbers themself respond to the value message and will return themself. Thus you can also provide a replacement value instead of an error block.
Number fromString: aString => someNumber or error
Number fromString: aString onError:[ errorValue ] => someNumber or fallBackValue
similar, but does not allow for garbage characters after the number (except spaces)
Integer readFrom: aStream
Integer readFrom: aStream onError:[...]
Float readFrom: aStream
Float readFrom: aStream onError:[...]
Integer fromString: aStream
Integer fromString: aStream onError:[...]
Float fromString: aStream
Float fromString: aStream onError:[...]
similar to the above, but these will return a correspondingly typed number (i.e. an instance of Integer, Float, etc.
formatString sscanf: aString => collection
formatString is a printf/scanf-like format string; reads items from aString and returns a collection (i.e. an Array) of scanned objects.
For example,
'%d %x %f' sscanf: '1234 FF 3.1415'
will return an array-like collection with 3 elements, the integer 1234, the integer 255 and the float 3.14159.
formatString scanf: aStream => collection
like above, but the elements will be read from a character stream
To read binary numbers, refer to the stream API.

Conversion[Bearbeiten]

In certain situations, it may be desirable to convert explicitly to a particular type, for example when binary data has to be verified or filled into a byte-buffer.

aNumber asInteger => Integer
truncates to an integer (i.e. same as "truncated")
aNumber asFloat => Float64
aNumber asFloat64 => Float64
aNumber asFloatD => Float64
generates a double precision float; may generate +/- INF if the value cannot be represented as a double IEEE float (i.e. is out of range). asFloat64 and asFloatD are aliases for compatibility.
aNumber asFloatChecked => Float64 or error
same as above, but reports an error if the value cannot be represented (instead of returning INF).
aNumber asShortFloat => Float32
aNumber asFloat32 => Float32
aNumber asFloatE => Float32
generates a single precision float; may generate +/- INF if the value cannot be represented as a single IEEE float. asFloat32 and asFloatE are aliases.
aNumber asShortFloatChecked => Float32 or error
same as above, but reports an error if the value cannot be represented (instead of returning INF).
aNumber asLongFloat => Float80
aNumber asFloatQ => Float80
generates an extended precision float; may generate +/- INF if the value cannot be represented as an extended IEEE float.
aNumber asLongFloatChecked => Float80 or error
same as above, but reports an error if the value cannot be represented (instead of returning INF).
aNumber asQDouble => QDouble
generates a qDouble
aNumber asQuadFloat => QuadFloat
aNumber asFloat128 => QuadFloat
generates a quadruple precision float (float128)
aNumber asOctaFloat => OctaFloat
aNumber asFloat256 => QuadFloat
generates an octuple precision float (float256)
aNumber asLargeFloatPrecision: numBits => LargeFloat
generates an large float with numBits precision
aNumber asLargeFloatDecimalPrecision: numDigits => LargeFloat
generates an large float with numDigits precision
aNumber asLargeFloat => LargeFloat
generates an large float with the same precision as aNumber
aNumber asFraction => Fraction
generates a fraction (from a float)
aNumber asScaledDecimal: scale => ScaledDecimal
generates a scaled decimal which presents scale fractional digits
aNumber asFixedDecimal: scale => FixedDecimal
generates a fixed decimal which rounds on and presents scale fractional digits
aNumber asComplex => Complex
generates a complex (with 0 as imaginary part, same as "nr + 0i")
aNumber i => Complex (that is a lower case i)
generates a complex (with 0 as real part, e.g. as in "0 + nr i")

Examples[Bearbeiten]

Square root of 2 with different precision[Bearbeiten]

nr := 2.0 sqrt.
'%.15g' printf:{nr}   
    => '1.4142135623731'
'%.30g' printf:{nr}   
    => '1.414213562373095101065700873732'
'%.50g' printf:{nr}   
    => '1.41421356237309510106570087373256683349609375'

Be reminded that these floats (which are IEEE doubles) only provide 15 digits of accuracy ("Float decimalPrecision" returns 15). Thus the above attempts to generate more digits are useless and excess digits are more or less random.

More valid digits are returned by QDoubles ("QDouble decimalPrecision" returns 61):

nr := 2.0 asQDouble sqrt.
'%.30g' printf:{nr}   
    => '1.41421356237309504880168872421'
'%.50g' printf:{nr}   
    => '1.4142135623730950488016887242096980785696718753769'
'%.100g' printf:{nr}   
    => '1.414213562373095048801688724209698078569671875376948073176679737988424424484343089516915416653038211'

Here again, digits after the 60th are wrong.

With octuple precision floats ("OctaFloat decimalPrecision" returns 71) we get:

nr := 2.0 asOctaFloat sqrt.
'%.30g' printf:{nr}   
    => '1.41421356237309504880168872421' (a quadruple precision float)
'%.50g' printf:{nr}   
    => '1.4142135623730950488016887242096980785696718753769'
'%.100g' printf:{nr}   
    => '1.41421356237309504880168872420969807856967187537694807317667973799073247801160833747418698891953623'

Finally, an arbitrary number of digits can be computed with LargeFloats (here we use a precision of 1000 bits for roughly 300 digits):

nr := (2.0 asLargeFloatPrecision:1000) sqrt.
'%.30g' printf:{nr}   
    => '1.41421356237309504880168872421'
'%.50g' printf:{nr}   
    => '1.4142135623730950488016887242096980785696718753769'
'%.100g' printf:{nr}   
    => '1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573'

In most situations, double precision is sufficient. However, some computations generate intermediate results which are outside the precision or range of IEEE doubles. See "Do not trust Floating Point" for a classic (surprising) example.


Reading Numbers[Bearbeiten]

readFrom: will not accept garbage characters after the number iff the argument is a string:

in := '123.456abc'.
Number readFrom: in.
    => error due to garbage after number ('abc')

However, it behaves different, if the argument is a stream.
Then the stream will be left positioned after the number's string:

Number readFrom: (in readstream).
    => 123.456
    (stream will be left positioned at the 'abc')

here, reading the rest after the number's digits:

s := in readstream.
val := Number readFrom: s.
rest := s upToEnd.
    => val: 123.456
       rest: 'abc'

you can provide an error-value:

val := Number readFrom:'bla' onError:[0]
    => val: 0

or perform any action inside the onError arg block:

val := Number readFrom:'blabla' onError:[ Dialog warn:'bad input'. nil ]
    => (Dialog shown)
       val: nil

an alternative to "readFrom:" is scanf, which can also read multiple values from a stream:

row := '%d %f %s' scanf:(ReadStream on:'1234 1111.2345 Fritz').
    => OrderedCollection(1234 1111.2345 'Fritz')
       i.e. an integer, a float and a string

or from a string:

myString := '1234 1111.2345 Fritz'.
row := '%d %f %s' scanf: myString.
    => OrderedCollection(1234 1111.2345 'Fritz')
       i.e. same as above

scanf can also be used to extract numbers which are not delimited by spaces (you have to specify the field length in the format):

myString := '1.234.5679875679'.
'%4f %5f %3d %4d' scanf:myString
    => OrderedCollection(1.23 4.567 987 5679)

Printf Format Specifier[Bearbeiten]

Characters not escaped by a '%' are printed as-is. Following a '%' there can be:

  • optional: '-' (POSIX refers to this as the <<flags>>)
  • optional: positive number or '*' (POSIX: <<width>>)
  • optional: period followed by positive number or * (POSIX: <<precision>>)
  • optional: an h or l to indicate size of data (POSIX: <<length>>)
  • required: character describing output behavior (POSIX: <<conversion specifier>>)

The format follows the official C-library printf formats; however, there are differences in the various printf implementations:

ANSI standards up through C99:

  • more flags: '+' ' ' '0' '#'
  • more lengths: 'L' 'hh' 'll' 'j' 'z' 't'
  • more conversions: 'F' 'a' 'A' 'n'

The POSIX specification of printf added:

  • positional parameters to identify argument indices
  • more flags: (single quote)
  • more conversions: 'C' 'S'
  • clarifications regarding corner cases and 'undefined behavior'

BSD implementations added:

  • more lengths: 'q'
  • more conversions: 'D' 'U' 'O'

glibc (GNU) added:

  • more lengths: 'Z'
  • more conversions: 'm'

Windows C Runtime (CRT) added:

  • more lengths: 'I' 'I32' 'I64' 'w'

glibc and CRT both added length 'Z'.

  • glibc uses 'Z' for the length size_t.
  • CRT uses Z as a conversion for length-prefixed strings.

The expecco/Smalltalk implementation handles 'Z' in the same way as 'z'.

BSD and IBM C library both added 'D'.

  • BSD uses D as a conversion, namely as an alias of 'ld'.
  • IBM uses 'D' for the length for _Decimal64, a decimal floating point type,
  • in accordance with ISO/IEC TR 24732.

The Smalltalk implementation takes the former approach.

The expecco/Smalltalkimplementation also adds new conversions:

  • 'b' and 'B' for binary (base-2) integer renderings
  • 'y' and 'Y' for true/false and yes/no Boolean conversions
  • 'J' for JSON (assuming that the object can be JSON-encoded)
  • 'T' and 'V' for JS typeof and valueOf inspection
  • 'S' for store-string (of any object)
  • 'P' for print-string (of any object)

Prefixes:

  • ' ' fill with spaces
  • '0' fill with zeros
  • '+' print the sign
  • '-' left justified
  • '#' depends:
    • %o, %x, %b: print base prefix
    • %e always show decimal point
    • %e, %E, %f, %g always show decimal point

Conversions:

  • 'a' (not implemented) hex floating point exp form
  • 'b' binary (base 2)
  • 'c' character or (first char of string)
  • 'd' integer
  • 'e' base-10 floating point exp form (scientific)
  • 'f' base-10 floating point decimal form (non-scientific)
  • 'g' 'e' or 'f', whichever looks more appropriate (based on the float-value)
  • 'i' integer (alias for 'd')
  • 'j' (not implemented) use 'J' for JSON format
  • 'n' (not implemented) stores number of characters written so far into arg
  • 'o' base-8 octal
  • 'p' (not implemented) pointer
  • 's' string
  • 't' type (i.e. class name)
  • 'u' (not implemented) unsigned (negative values are converted)
  • 'v' (not implemented) store string
  • 'x' base-16 hex
  • 'X' base-16 hex upper case

Parameter selection (not implemented):

  • <n>$ take n'th parameter

Dynamic width/precision (consumed in order as presented):

  • "*" take width/parameter from next argument

Special output specifier:

  • <n>! if the number's string is larger than the field width <n>, it will be filled with '#'s. Useful if you want to ensure tabular data to remain aligned. This is not a posix printf specified, but a Smalltalk/X extension.

Examples 1):

'|%d|'   printf: { 123 }         -> '|123|'
'|%5d|'  printf: { 123 }         -> '|  123|'
'|%-5d|' printf: { 123 }         -> '|123  |'

'|%s|'  printf: { 'abc' }        -> '|abc|'
'|%5s|' printf: { 'abc' }        -> '|  abc|'
'|%*s|' printf: { 5 . 'abc' }    -> '|  abc|'

'|%f|'    printf: { 1.234 }       -> '|1.234|'
'|%#f|'   printf: { 1.234 }       -> '|1.234000|'
'|%8f|' printf: { 1.234 }        -> '|   1.234|'
'|%*f|' printf: { 8 . 1.234 }    -> '|   1.234|'
'|%10f|'  printf: { 1.234 }       -> '     1.234'
'|%#10f|' printf: { 1.234 }       -> '  1.234000'

Negative width will fill at the right:

'|%5s|'  printf: { 'abc' }       -> '|  abc|'
'|%-5s|' printf: { 'abc' }       -> '|abc  |'
'|%-*s|' printf: { 5 . 'abc' }   -> '|abc  |'
'|%*s|'  printf: { -5 . 'abc' }  -> '|abc  |'

'|%-8f|' printf: { 1.234 }       -> '|1.234   |'
'|%*f|'  printf: { -8 . 1.234 }  -> '|1.234   |'
'|%-*f|' printf: { 8 . 1.234 }   -> '|1.234   |'
'|%-*f|' printf: { -8 . 1.234 }  -> '|1.234   |'

A Zero as fill character (only at the left):

'|%05s|'  printf: { 'abc' }      -> '|00abc|'
'|%05d|'  printf: { 123 }        -> '|00123|'

Field width overflow:

'|%4d|' printf: { 123456 }       -> '|123456|'
'|%4!d|' printf: { 123456 }      -> '|####|'


The case (upper vs. lower) of the float-format character affects printing of Nan, Infinity and exponent separator:

'%f' printf: { 1.234 }                 -> '1.234000'
'%F' printf: { 1.234 }                 -> '1.234000'
'%e' printf: { 1.234 }                 -> '1.234e0'
'%E' printf: { 1.234 }                 -> '1.234E0'
'%f' printf: {Float NaN}               -> 'nan'
'%F' printf: {Float NaN}               -> 'NAN'
'%f' printf: {Float infinity}          -> 'inf'
'%F' printf: {Float infinity}          -> 'INF'
'%f' printf: {Float negativeInfinity}  -> '-inf'   
'%F' printf: {Float negativeInfinity}  -> '-INF'
'%-F' printf: {Float infinity}         -> '+INF'
'%-F' printf: {Float negativeInfinity} -> '-INF'
'% F' printf: {Float infinity}         -> ' INF'
'% F' printf: {Float negativeInfinity} -> '-INF'

1) Reminder: the "{ ... }" syntax in Smalltalk generates an Array containing the elements (expressions) separated by periods. I.e. "{ 1+2 . 3+4 }" would generate an array with 2 elements: 3 and 7.
With constant arguments, this is (almost) equivalent to #( el1 el2) (without periods). Except for the fact, that constant arrays are immutable (readonly), whereas the brace construct instantiates a new array which is mutable.

Scanf Format Specifier[Bearbeiten]

The Smalltalk implementation adds new conversions:

Conversions (upper case same as lower case):

  • 'b' binary (base 2)
  • 'c' character or (first char of string)
  • 'd' decimal
  • 'e' float
  • 'f' float
  • 'g' float
  • 'i' integer (alias for 'd')
  • 'o' base-8 octal
  • 's' string
  • 'u' integer
  • 'x' base-16 hex
  • 'n' any number
  • 'J' JSON object (upper case 'J' only)

Length prefix:

  • 'h' with float formats: reads as ShortFloat
  • 'L' with float formats: reads as LongFloat

Examples:

'%d %x' sscanf:'1234 ff00'         -> OrderedCollection(1234 65280)
'%d %s' sscanf:'1234 ff00'         -> OrderedCollection(1234 'ff00')
'%d %x %b' sscanf:'1234 ff00 1001' -> OrderedCollection(1234 65280 9)
('%f' sscanf:'1234') first         -> 1234.0 (Float i.e. an IEEE double)
('%lf' sscanf:'1234') first        -> 1234.0 (Float i.e. an IEEE double)
('%llf' sscanf:'1234') first       -> 1234.0 (Float i.e. an IEEE double)
('%hf' sscanf:'1234') first        -> 1234.0 (ShortFloat i.e. an IEEE single)
('%Lf' sscanf:'1234') first        -> 1234.0 (LongFloat i.e. an IEEE extended)
('%LLf' sscanf:'1234') first       -> 1234.0 (QDouble)

See Also[Bearbeiten]

Numeric Limits provides additional info on precision, ranges and problems with floating point numbers.



Copyright © 2014-2024 eXept Software AG