Number API Functions: Unterschied zwischen den Versionen

Aus expecco Wiki (Version 2.x)
Zur Navigation springen Zur Suche springen
(10 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 132: Zeile 132:


Fractions print themself as "(''a'' / ''b'')".
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 ==
== Scaled Decimals ==
Zeile 224: Zeile 225:
Normally, there is no need for explicit conversion between number types. The result of mixed operations is the computed with the type of the operand which has the higher "''generality''".
Normally, there is no need for explicit conversion between number types. The result of mixed operations is the computed with the type of the operand which has the higher "''generality''".
The order of generalities is:
The order of generalities is:
Integer < Fraction < ScaledDecimal < FixedDecimal < Float32 < Float64 < Float80 < Complex
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).
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).
<br>When an operation involves a float and an integer or fraction, the result will be a float.
<br>When an operation involves a float and an integer or fraction, the result will be a float.
Zeile 316: Zeile 318:
::The usual arithmetic operators.<br>
::The usual arithmetic operators.<br>
::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.
::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.
::[[Datei:point_right.png|20px]] Notice, that they are evaluated left to right, without special precedences.
::[[Datei:point_right.png|20px]] Notice, that Smalltalk evaluates them left to right, without special precedences.<br>Thus you should always use parentheses to group expressions when there are two or more operators in an arithmetic expression.
::Thus you should always use parentheses to group expressions when there are two or more operators in an arithmetic expression.


''aNumber'' <code>**</code> ''aNumber'' => Number
''aNumber'' <code>**</code> ''aNumber'' => Number

Version vom 19. Oktober 2021, 00:18 Uhr

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.

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
16rFFAA
or 0xaffe
2r0101
or 0b101010
8r377
or 0o377
<N>rXXX
1234567890123456789012345678901234567890
-123456789012345678901234567890

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
1345.6789q5

float constant; actually double precision;
use "q" instead of "e" for extra precision (extended IEEE floats)
Fraction Literals[Bearbeiten]

(4/3)
(523423432/3)

fraction constants (numerator / denominator); these are exact
Scaled Decimal Literals[Bearbeiten]

123.456s2
100s2

scaled decimal; prints itself rounded to 2 fractional digits eg. "123.46" or "100.00" (although internally, the full precision is kept for further operations)
Complex Number Literals[Bearbeiten]

(4+3i)
(4.3+3.1i)
5.0 i

a complex number (real part / imaginary part)

Wellknown Constant Numbers[Bearbeiten]

A few constants are known by name. They are answered by corresponding getter messages sent to the number class (of which you want the constant):

Float pi

pi as IEEE double precision number

LongFloat pi

pi as IEEE extended precision number

Float ln2
Float ln10
Float phi
Float sqrt2
Float e

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".

There is usually no need to explicitly use or refer to ShortFloats: 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).

Float[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.

ShortFloat[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[Bearbeiten]

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

Floats print themself with either a decimal point or an exponent indicator 'e', eg. "0.5", "10.0" or "1.3e3"

Experimental Extra Float Representations[Bearbeiten]

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.

QDouble[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 (1e200 + 1e-15) - 1e200 -> 0.0(floats loose the small value), whereas 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)
Due to the extra processing overhead, operations are slower than with doubles or extended doubles.
QuadFloat[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 slower than both regular floats and also slower than QDoubles.

OctaFloat[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, and slower than QuadFloats.

LargeFloat[Bearbeiten]

LargeFloats use an arbitrary (configurable) number of bits to represent floats with any precision.
They are completely software emulated which makes operations much slower than with other floats.

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).

However, this will look strange (i.e. wrong) if monetary values are presented this way, eg. on an invoice's summation. Here, we 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 eg. 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 eg. in an invoice's sum.

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 the decimal to round the internal value to the shown scale (as described above).

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 (eg. "5 i" yields (0 + 5 i).
Complex numbers print themself as "(a + b i)".

Complex results can also be returned from eg. square root (sort) and logarithm (log, ln) operations IFF imaginary results are trapped. I.e.

-4 sqrt

will report an error, whereas:

Number trapImaginary:[ -4 sqrt ]

will return a complex result.

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 parts 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 (eg. 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 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).

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")

Operations with Mixed Types[Bearbeiten]

Normally, there is no need for explicit conversion between number types. The result of mixed operations is the computed with the type of the operand which has the higher "generality". 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.

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. Eg. "(10 ± 1) + 10" yields "(20 ± 1)".

aMeasurementValue * aNumber => MeasurementValue
aMeasurementValue / aNumber => MeasurementValue

the error will also be scaled by aNumber. Eg. "(10 ± 1) * 10" yields "(100 ± 10)".

 

PhysicalValues[Bearbeiten]

PhysicalValues can only be scaled by a scalar value; addition and subtraction are not allowed:

aPhysicalValue + aNumber => error
aPhysicalValue - aNumber => error

not allowed

aPhysicalValue * aNumber => aPhysicalValue
aPhysicalValue / aNumber => aPhysicalValue

for example, "10 volt * 10" gives "100 volt".

 

Most Common/Useful Operations[Bearbeiten]

Testing[Bearbeiten]

aNumber isFinite => Boolean

Check if number is not infinity and not NaN:

 

aNumber isInfinite => Boolean

Check if number is either positive infinity (INF) or negative infinity (-INF):

 

aNumber isNaN => Boolean

Check if number is NaN ("Not a Number"):

 

aNumber isInteger => Boolean

Check if number is an integral number.

 

aNumber isFraction => Boolean

Check if number is a fractional number.

 

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

 

anInteger nextPrime => anInteger
anInteger nextPowerOf2 => anInteger  

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.

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

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

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
aNumber integerSqrt => Number

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
aNumber integerCbrt => Number

cubic root and truncated 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

Bitwise Operators[Bearbeiten]

integer1 bitAnd:integer2 => Integer
integer1 bitOr:integer2 => Integer
integer1 bitXor:integer2 => Integer
integer1 bitShift:count => Integer

left shift if count is positive; right shift if negative


integer1 leftShift:count => Integer
integer1 rightShift:count => Integer
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


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 (eg. 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)

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.
  • 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 habe 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. "Number readFrom:(someString readStream). instead of "Number fromString:someString"

Numbers are read by sending the Number-class a "readFrom:" or a "fromString:" message. If the class is the abstract class Number, then the read code will itself figure out, what kind of number to return. If the given class is a concrete class (Float, Integer, Fraction etc.), you will get an instance of that class, unless the characters o 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 any of the number types


Number readFrom: aStream onError:[ errorValue ] => someNumber or errorValue

errorValue (which is a Smalltalk block), can be a constant, an arbitrary Smalltalk expression or even show a warn dialog or do whatever you like

Number fomString: aString => someNumber or error
Number fromString: aString onError:[ errorValue ] => someNumber or fallBackValue

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, but these will return a corresponding typed number

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

Truncation and Rounding[Bearbeiten]


aNumber truncated => Integer

truncates towards zero


aNumber rounded => Number

rounds up/down towards the nearest integer


aNumber ceiling => Number

returns the next larger integer (unless aNumber is integral). I.e. truncates towards positive infinity.


aNumber floor => Number

returns the next smaller integer (unless aNumber is integral). I.e. truncates towards negative infinity.


aNumber roundTo: grid => Number

rounds up/down towards the nearest multiple of grid. I.e. "1.284 roundedTo:0.1" yields "1.3".


aNumber truncateTo: grid => Number

truncates towards the nearest multiple of grid. I.e. "1.284 truncateTo:0.1" yields "1.2".

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 (i.e. same as "truncated")


aNumber asFloat => Float64

generates double precision float; may generate +/- INF if the value cannot be represented as a double IEEE float (i.e. is out of range).


aNumber asFloatChecked => Float64 or error

same as above, but generates an error if the value cannot be represented.


aNumber asShortFloat => Float32

generates single precision float; may generate +/- INF if the value cannot be represented as a single IEEE float.


aNumber asShortFloatChecked => Float32 or error

same as above, but generates an error if the value cannot be represented.


aNumber asLongFloat => 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 generates an error if the value cannot be represented.


aNumber asQDouble => QDouble

generates a qDouble (from a float or integer)


aNumber asQuadFloat => QuadFloat

generates a quadruple precision float (from a float or integer)


aNumber asOctaFloat => OctaFloat

generates an octuple precision float (from a float or integer)


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")

Examples[Bearbeiten]

Square root of 2 with different precision:

nr := 2.0 sqrt.
'%.30g' printf:{nr}   
-> '1.414213562373095101065700873732' (a float)
'%.50g' printf:{nr}   
-> '1.41421356237309510106570087373256683349609375'

Be reminded that these floats (which are IEEE doubles) only provide 15 digits of accuracy ("Float decimalPrecision" returns 15).
More valid digits are returned by QDoubles ("QDouble decimalPrecision" returns 61):

nr := 2.0 asQDouble sqrt.
'%.30g' printf:{nr}   
-> '1.41421356237309504880168872421' (roughly 200 bits precision)
'%.50g' printf:{nr}   
-> '1.4142135623730950488016887242096980785696718753769'
'%.100g' printf:{nr}   
-> '1.414213562373095048801688724209698078569671875376948073176679737988424424484343089516915416653038211'

or with octuple precision floats ("OctaFloat decimalPrecision" returns 71):

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 1000 bits for roughly 300 digits precision):

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

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 were 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 Smalltalk implementation takes the former approach, handling '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 Smalltalk implementation 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
  • 'T' and 'V' for JS typeof and valueOf inspection
  • 'S' for store-string
  • 'P' for print-string

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 (upper case same as lower case, except for xX):

  • '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 value)
  • 'i' integer (alias for 'd')
  • 'j' (not implemented) 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

Examples:

'|%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|'

Case of 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'

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

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)



Copyright © 2014-2024 eXept Software AG