This chapter describes GemStone’s Numeric and Time-related classes.
This includes Numbers, such as Integers, floating point, fractions. Most numbers can be specified as literals within your code, and most numbers can be used in expressions with, or converted to, other types of numbers.
Also included are Time-related classes, such as Date, Time, DateTime, and DateAndTime.
Integers
Describes classes that represent whole numbers: SmallInteger and LargeInteger.
Binary Floating Point
Describes classes for binary floating point numbers: SmallDouble and Float.
Other Rational Numbers
Describes classes for other rational numbers with different ranges and precisions, including Fraction, FixedPoint, ScaledDecimal, and DecimalFloat.
Dates and Times
Describes the classes that represent times.
Internationalizing
How to control the display of decimal points.
Random Numbers
Information on the set of random number generator classes, providing random numbers of various purposes.
Integers in GemStone are composed of SmallIntegers and LargeIntegers. Most Integers you are likely to use will be SmallIntegers, in the range of -260 to 260 -1. Integers outside this range are represented by LargeIntegers. Operations that result in a value outside the SmallInteger range transparently result in LargeIntegers, and vice-versa
The literal syntax for Integer will create either a SmallInteger or LargeInteger.
Integers can be specified using radix notation, using the r or # characters.
For example, to specify the hex SmallInteger value FF, the following are all valid:
FFr16
FF#16
Number fromString: 'FFr16'
'ff#16' asNumber
SmallIntegers are special (immediate) objects, that is, the number itself is encoded in the OOP, making instances of this class both small (since no further storage is required) and fast. They are also unique, so SmallIntegers of the same value are always identical (==) as well as equal (=).
SmallIntegers have a range from -260 to 260 -1. Values outside this range must be represented as LargeIntegers.
LargeIntegers are not special objects; they require an OOP.
Each instance of LargeInteger is stored as an array of bytes, where every 4 bytes represents a base 4294967296 digit. The first 4 bytes are the sign digit (0 or 1), the next 4 bytes in that array constitute the least significant base 4294967296 digit, and the last 4 bytes are the most significant base 4294967296 digit.
Instances of LargeInteger have a maximum size of 4067 digits plus the sign. The maximum absolute value for a LargeInteger is (2130144 - 1). Attempting to create a LargeInteger that exceeds this maximum will fail with an Integer overflow error.
Floating point values in GemStone are composed of SmallDoubles and Floats. The most commonly used floating points will be SmallDoubles. While both SmallDouble and Float represents 8-byte binary floating point numbers, as defined in IEEE standard 754, SmallDoubles have a reduced exponent range. Some floating point values therefore can only be represented by instances of Float, rather than SmallDouble. Similarly to SmallInteger and LargeInteger, GemStone operations return one or the other as needed.
The numerical behavior of instances of Float is implemented by the mathematics package of the vendor of the machine on which the Gem process is running. There are slight variations in results with different platform’s implementation of the
IEEE-754 standard.
You can get the components of a floating point value using the methods signBit, exponent, and mantissa.
SmallDoubles are special objects; as with SmallIntegers, the number itself is encoded in the OOP, making instances small and fast. They are also unique, so SmallDoubles of the same value are identical (==) as well as equal (=).
Each SmallDouble contains a 61 bit value, in IEEE format but with reduced exponent range. There is 1 sign bit, 8 bits of exponent and 52 bits of fraction. SmallDoubles are always in big-endian format (both on disk and in memory).
SmallDoubles can represent C doubles that have value zero or that have exponent bits in range 0x381 to 0x3ff, which corresponds to about 5.0e-39 to 6.0e38; approximately the range of C 4-byte floats.
Floats are not special objects; they require an OOP.
Each Float contains a 64 bit value in IEEE format, with 1 sign bit, 11 bits of exponent and 52 bits of mantissa. Floats are in cpu-native byte order when in memory, and the byte order of the extent when on disk.
In addition to the finite numbers, the IEEE standard defines floating point formats to include Infinity (positive and negative) and NaNs (not a Number), which can be quiet or signaling. NaNs results from an operations whose result is not a real number, such as:
-23 sqrt
%
PlusQuietNaN
Infinity results from operations that return a value outside the range of representation, such as:
32.0 / 0
%
PlusInfinity
ExceptionalFloats are named, unique instances of Float, not of SmallDouble. Exceptional Floats include:
PlusInfinity
MinusInfinity
PlusQuietNaN
MinusQuietNaN
PlusSignalingNaN
MinusSignalingNaN
Since the sign of NaNs is not defined, GemStone operations return only positive NaNs; they do not return MinusQuietNan or MinusSignalingNan.
An unusual quality of NaNs is that they are not equal to themselves. This means that NaNs can cause problems if used as keys of hashed equality-based collections.
PlusQuietNaN = PlusQuietNaN
%
false
When performing operations on Floats, an ExceptionalFloat may not always be an appropriate result.
You can determine if a number is an ExceptionalFloat using the message #isExceptionalFloat.
You can configure your system to signal an exception, rather than return an ExceptionalFloat. The following are the types of Floating point error conditions that may arise:
FloatingPointError has protocol to configure signalling for all or none of these error conditions, or any subset. For example,
FloatingPointError enableAllExceptions.
FloatingPointError enableExceptions: { #divideByZero }
After enabling exceptions, exceptional conditions will signal errors, rather than returning an exceptional Float, for the duration of that session.
Literal numbers in evaluated code that include a decimal point by default create a SmallDouble or Float. If the value is in the SmallDouble range, a SmallDouble will be created, otherwise a Float will be created.
Literal floats may be specified using exponential notation. For example, 5.1e3 and 5.1e-3 are valid SmallDouble literals.
ANSI specifies that float values may have exponents e, d, or q. These exponents, as well as E and D, are legal in GemStone, but have the same result: a SmallDouble or Float. Likewise, the ANSI class names FloatE, FloatD, and FloatQ can be used in code, but all resolve to Float class.
Note that using a plus sign before the exponent is not allowed in literal floats, although it can be used to create floating points from strings (using Float fromString:). This avoids ambiguity with Smalltalk dialects that would interpret this as the addition operator. For example, 5.1E+3, which historically GemStone would interpret as the same as 5.1E3, is disallowed; code must either omit the +, or include white space to clarify the addition operator.
SmallDoubles and Floats are printed by default using asString or printString, in the notation equivalent to the C printf expression %.16g. This provides a maximum of 16 significant digits, rounding the fractional portion and changing to exponent notation if the whole number portion has more than 16 digits.
You can use asStringUsingFormat: to control the details of how floating point numbers are formatted when printing. asStringUsingFormat: accepts an Array of three elements:
12.3456 asString
%
12.3456
12.3456 asStringUsingFormat: #(-8 2 false)
%
12.35
12.3456 asStringUsingFormat: #(4 10 true)
%
1.2345600000e01
For some application, binary floating points are problematic, since there are common decimal values that cannot be expressed exactly in binary floating point; for example, 5.1 does not have a precise binary floating point representation. This can make computation results incorrect. For example:
5.1 * 100000
%
509999.9999999999
There are several options to avoid this: Fraction, FixedPoint, ScaledDecimal, and DecimalFloat. These classes are independent of each other, and each provides different qualities of precision and range.
Fractions precisely represent rational numbers. Fractions are composed of an integer numerator and an integer denominator. As the ratio of two Integers, fractions can represent any rational number to an unbounded level of precision.
The display of fractions is as the numerator and denominator separated by the $/ character, which is also the division binary method. Fractions have no literal representation. An expression such as 1/3, which performs a division of two Integers, will return a fraction if the result is not an Integer.
(1/3) printString
%
1/3
Any expression, not just division expressions, that could result in fractions will be reduced automatically, to the lowest fraction or to an Integer.
(5/6) + (1/6)
%
1
SmallFractions are special objects, in which the OOP itself encodes the value. As with SmallDouble and Float, creating a fraction will result in either an instance of SmallFraction or Fraction, depending on the specific value.
SmallFractions can hold objects with numerators between -536870912 and 536870911, and denominators from 1 to 134217727.
ScaledDecimals represent a decimal number to the precision of a fixed number of fractional digits. ScaledDecimals are composed of an integer mantissa and a power-of-10 scale.
Literal ScaledDecimal or SmallScaledDecimals can be created using the s notation; for example, 1.53s2. This is not an exponential notation; the 2 here is the scale, and mantissa is resized appropriately. The values 1.53s2, 1.53s3, and 1.53s4 are all equal.
The number of fractional digits must not be greater than the scale.
For returned values from mathematical operations, ANSI does not precisely specify the scale of a returned ScaledDecimal. The following rules are used:
For some mathematical operations, the returned value type is a ScaledDecimal, but the returned value cannot always be exactly represented as a ScaledDecimal with the correct scale. In these cases, the results are rounded using the following rules:
SmallScaledDecimals are special objects, in which the OOP itself encodes the value. As with SmallDouble and Float, creating a ScaledDecimal will result in either an instance of SmallScaledDecimal or ScaledDecimal, depending on the specific value.
SmallScaledDecimals can hold values with a scale <= 31, and a mantissa in the range -2^50 (-1125899906842624) to -2^50 (1125899906842623).
If the scale or mantissa is outside the SmallScaledDecimal range, an instance of ScaledDecimal is created. These are not special objects. The maximum scale of a ScaledDecimal is 30000.
While ScaledDecimals represent decimal fractions to the precision specified, most floating point values cannot be represented exactly by ScaledDecimals. The system will error if there is an attempt to create a ScaledDecimal with more than 39177 decimal digits.
FixedPoints, like Fractions, represents rational numbers, but also include information on how they should be displayed. A FixedPoint is composed of an integer numerator, integer denominator, and an integer scale. Like Fraction, this allows rational numbers to be represented with unbounded precision, and since fractional arithmetic is used in calculations, numerical results do not lose precision. The scale provides automatic rounding when representing the FixedPoint as a String.
FixedPoint is a legacy format provided for backwards compatibility. New code should use ScaledDecimal or Fraction.
FixedPoint uses a literal notation using p, such as 1.23p2. This is not an exponential notation; the 2 here specifies scale. The values 1.23p2, 1.23p3, and 1.23p4 are all equal.
DecimalFloats represent base 10 floating point numbers, per IEEE standard 854-1987.
Literal DecimalFloats can be specified in exponential notation using the f or F character; for example, 5.432F2 creates a DecimalFloat equivalent to 543.2.
Objects of class DecimalFloat have 20 digits of precision, with an exponent in the range -15000 to +15000. The first byte encodes the sign and kind of the floating-point number. Bit 0 is the sign bit. The values in bits 1 through 3 indicate the kind of DecimalFloat:
001x = normal
010x = subnormal
011x = infinity
100x = zero
101x = quiet NaN
110x = signaling NaN
Bytes 2 and 3 encode the exponent as a biased 16-bit number (byte 2 is more significant). The actual exponent is calculated by subtracting 15000. Bytes 4 through 13 form the mantissa of the number. Each byte holds two BCD digits, with bits 4 through 7 of byte 4 containing the most significant digit.
Similarly to Float, operations that would not result in a real number, or that produce a result outside the representable range, result in Exceptional numbers:
DecimalPlusInfinity
DecimalMinusInfinity
DecimalPlusQuietNaN
DecimalMinusQuietNaN
DecimalPlusSignalingNaN
DecimalMinusSignalingNaN
You can determine if a number is an ExceptionalFloat using the message #isExceptionalFloat.
The following table lists the notations that may appear in a literal number.
You can instruct the compiler to understand a new numerical literal format by sending a message to your customized subclass of Number to register that format.
The following method provides this registration:
Number >> parseLiterals: aCharacter exponentRequired: aBoolean
Once this is sent to an instance of a subclass of Number, when the compiler encounters a numeric value using aCharacter, it will send fromString: to that class.
For example, say you have defined a class ComplexNumber. For the literal format, you wish to use NiM, where N represent the real part and M represents the imaginary part. So for example, 4.5+5i would be specified using the literal form 4.5i5.
First, you would define the ComplexNumber>>fromString: method, which will parse a string of the form NiM and return the new instance of ComplexNumber.
Then, to allow the literals to be included in code, send the following message.
ComplexNumber parseLiterals: $i exponentRequired: true
Now, assuming you have implemented the behavior appropriately, the compiler can evaluate expressions of the form:
(3.5i5 + 7.1i3) asString
%
10.6i8.0
Once invoked, the new literal format will be recognized until the session logs out.
Note that for subsequent logins, compiled references to that literal will continue to be valid, but unless the method is invoked again, methods with that literal cannot be recompiled. Including the invocation of parseLiterals:exponentRequired: in session initialization code (such as using loginHook:) is recommended.
To uninstall a custom literal without logging out, use the same method, passing in nil for aBoolean. For example,
When a mathematial operation is performed on numeric values, the class of the result depends on the specific classes of the argument and receiver.
By default, the result will be according to ANSI, per the following table.
So, for example, the result of 1 * 0.5 is a SmallDouble, and the result of 1/3 - 1.50s2 is a SmallFraction.
Note that the legacy classes FixedPoint and DecimalFloat do not reliably conform to this standard; this maintain historic behavior for legacy applications.
Conversion is supported between kinds of numbers and from kinds of numbers to String, using asInteger, asFloat, asFraction, and so on; see the image for specifics. Note that converting to a ScalledDecimal or FixedPoint requires a scale argument.
In cases when floating points are involved, the precision limits may result in a converted value that is slightly different than you might expect.
For example, when printing the following SmallDouble using asStringLegacy (which uses exponential notation to print all digits of precsion), the printed value varies slightly at the maximum digits of precision.
1.111222233334444 asStringLegacy
%
1.1112222333344439E00
The methods roundTo: and truncateTo:, and related selectors, allow you to reduce unnecessary fractional parts.
For display, this can also be done using asStringUsingFormat: methods that allow you to specify the number of digits of a float, for example.
truncateTo: returns the multiple of the argument that is closest to the receiver towards zero.
roundTo: returns the multiple of the argument that is closest to the receiver in either direction; if the receiver is exactly between to multiples, the multiple farther from zero is returned. roundedHalfToEven: allows you to round, and if the receiver is exactly halfway between multiples, return the even one.
The result of truncateTo: and roundTo: follows the ANSI standard, and conforms to table on Table 6.2. However, for truncation and rounding it is useful to be get a result that is the class of the argument; since, for example, 3.123 roundTo: 1 returns a SmallDouble, 3.0.
The methods truncated and rounded perform truncateTo:/roundTo: to 1, and return an Integer. When truncating or rounding other than to 1, you can use the methods truncateAndCoerceTo: and roundAndCoerceTo:, which return an instance of the class of the argument.
GemStone supports the date-time clases Date, Time, and DateTime and DateAndTime. Using date-time clases requires taking into account the TimeZone, the current local offset from UTC (GMT).
An instance of Date describes a month, day and year in time.
Date supports dates after December 31, 1900. While Dates earlier than this can be created and operated on, they are not tested and not officially supported. Technically legal years are in the range -231 (-2147483648) to 231 - 1 (2147483647).
An instance of SmallDate is a special (that is, the OOP encodes the value), encoding the day of year and the year within the OOP. Newly created Date instances are instances of SmallDate.
All possible supported Dates can be represented as SmallDates. All newly created instances of Date are returned as instances of SmallDate, but existing instances of Date remain in upgraded repositories. Date and SmallDate are interoperable with each other, and the following discussion uses Date to refer to either Date or SmallDate.
Date instances can be created from formatted strings or streams, or by using instance creation methods that allow you to specify the properties. See the image for the available options. For example:
Date today
Date fromString: '21/07/2023'
Date newDay: 21 month: 'July' year: 2023
Date supports printing methods and reading methods that use an explicit string-formatting Array. For Date, this is a 6-element Array that is passed to Date >> asStringUsingFormat:, or fromString: usingFormat: and related instance creation methods.
The default is DD/MM/YYYY, equivalent to #(2 1 3 $/ 1 1). Note that the day is first, not the US convention of month first.
(Date fromString: '21/07/2023') monthName
'July'
(Date today) asStringUsingFormat: #(3 2 1 $. 1 1)
'2023.07.21'
An instance of Time describes a time of day.
An instance of SmallTime is a special (that is, the OOP encodes the value), in microseconds resolution, using 56 bits of the OOP. Since there are 86400000000 microseconds in a day, all possible Times can be represented as SmallTimes. All newly created instances of Time are returned as instances of SmallTime, but existing instances of Time remain in upgraded repositories. Time and SmallTime are interoperable with each other, and the following discussion uses Time to refer to either Time or SmallTime.
Time instances can be created from formatted strings or streams, or by using instance creation methods that allow you to specify details. See the image for the available options. For example:
Time now
Time fromString: '17:23:05'
Time fromSeconds: 34234
Explicit string-formatting specifications take the form of a 3-element Array that is passed to Time >> asStringUsingFormat:, or fromString:usingFormat: and related instance creation methods. In this array:
The default is #($: true false), equivalent to HH:MM:SS.
Time fromString: '23.34' usingFormat: #( $. false false)
23:34:00
Time now asStringUsingFormat: #($: false true)
'02:30 PM'
Time instances themselves have no TimeZone. Class creation methods, and methods that print or display Times, that have "gmt" in the selector, interpret the time as GMT and apply the offset from the repository setting for TimeZone current.
For example, in the America/LosAngeles TimeZone:
Time fromStringGmt: '11:30:00'
04:30:00
(Time fromStringGmt: '11:30:00') asStringGmt
'11:30:00'
DateTime represents a point in time with millisecond resolution. DateTime supports points in time after midnight on December 31, 1900 at midnight GMT. While Dates earlier than this can be created and operated on, they are not tested and not officially supported.
A DateTime includes the year, day of year, milliseconds, and a TimeZone.
Date instances can be created from formatted strings or streams, or by using instance creation methods that allow you to specify the properties. See the image for the available options. For example,
DateTime now
DateTime fromString: '21/07/2023 23:15:26'
DateTime newWithYear: 2023 month: 7 day: 21 hours: 15minutes: 26 seconds: 0
Explicit string-formatting specifications take the form of a Array of elements that is passed to DateTime >> asStringUsingFormat:, or fromString:usingFormat: and related instance creation methods.
This Array must have at least 8 elements; 4 additional elements are optional.
The default is (1 2 3 $/ 1 1 $: true true false false false), equivalent to (DD/MM/YYYY HH:MM:SS).
For example, to read a non-default formatted string, and create an instance of DateTime, which then by default prints in the default format:
DateTime fromString: 'January 7 2023 9:45 pm' usingFormat:
#(2 1 3 $ 3 1 $: true false true false)
07/01/2023 21:45:00
DateAndTime is the ANSI compliant class that is equivalent to DateTime, and represents a point in time. DateAndTime instances know their microseconds (plus or minus) since 00:00:00 on January 1 2001, UTC (not counting leap seconds), and the TimeZone offset in seconds.
There is no restriction on the year range for DateAndTime. DateAndTimes are in the Gregorian calendar (the common calendar adopted in Europe in 1582). Date times prior to the adoption of this calendar are given in the retrospective astronomical Gregorian calendar. The year 1 A.D.is astronomical Gregorian year 1, the year 1 B.C. is astronomical Gregorian year 0, the year 2 B.C. is astronomical Gregorian year -1, and so on.
DateAndTime instances are always created with a resolution of 6 decimal places, equivalent to microsecond resolution.
An instance of SmallDateAndTime is a special (that is, the OOP encodes the value), that represents DateAndTimes in the range of from January 1, 2001 to May 10, 2072, that have timezone offsets in integer hours, in the range -16..15. Creating a DateAndTime will return an instance of SmallDateAndTime if it is within the range, otherwise it will return an instance of DateAndTime.
DateAndTime instances can be created from formatted strings or streams, or by using instance creation methods that allow you to specify details. See the image for the available options. For example:
DateAndTime now
DateAndTime fromString: '2023-07-21T15:26:00-08:00')
DateAndTime year: 2023 month: 07 day: 21 hour: 15minute: 26 second: 0 offset: (Duration seconds: -28800)
The format for reading and printing DateAndTime is
[-]YYYY-MM-DDTHH:MM:SS[.SSSSSS]±hh:mm
Sending printString returns all digits of the DateAndTime seconds, while asString does not print fractional seconds.
(DateAndTime fromString: '2023-07-21T13:06:15-00:00')
printString
'2023-07-21T13:06:15+00:00'
(DateAndTime fromString: '2023-07-21T13:06:15.12356789-07:00')
printString
'2023-07-21T13:06:15.123568-07:00'
(DateAndTime fromString: '2023-07-21T13:06:15.12356789-07:00')
asString
'2023-07-21T13:06:15-07:00'
Each instance of DateTime includes a reference to a TimeZone object, which handles the conversion from the internally stored Greenwich Mean Time (GMT)/Coordinated Universal Time(UTC) and the local time. TimeZones are also used to determine the local time offset for instances of DateAndTime now.
TimeZones encapsulate the daylight savings time (DST) rules, so a given GMT/UTC time is adjusted to local time based on TimeZone and the specific date.
Each session has a current TimeZone, which is used to display times, and to create instance of date and time classes when using methods that do not explicitly specify the TimeZone.
The current TimeZone (TimeZone current) is set from the default TimeZone (TimeZone default) during login. The default TimeZone is persistent, and can only be updated by SystemUser. The GemStone distribution comes with the America/Los_Angeles TimeZone installed as the default TimeZone. This is described in the GemStone/S 64 Bit Installation Guide, and instructions for updating the current TimeZone are in the System Administration Guide.
DateTime method selectors and comments refer to GMT, which is the older term; DateAndTime refers to UTC, which is the current preferred term.
The convention for expressing numbers and dates varies in different countries. GemStone supports several ways to handle customization from the default display.
The timestamps printed in the log headers and in log messages are formatted according to the current system locale. You can override this using the GS_CFTIME environment variable. If this is set in the environment for the process, then the setting is used to control printing in log headers and log messages.
The setting for GS_CFTIME must be a valid strftime format string, and must contain fields for:
If these criteria are not met, the default date format based on the system’s LOCALE is used, or otherwise the US-centric date format. See the man page for strftime, for details on the formats.
EXPORT GS_CFTIME="%Y-%m-%d %H:%M:%S %Z"
Will include lines such as the following in the Gem log header:
| PROCESS ID: 2120954 DATE: 2023-07-21 16:20:53 PDT (UTC -7:00)
...
| DATEFORMAT: %Y-%m-%d %H:%M:%S %Z
The class Locale allows you to obtain operating system locale information and use or override it in GemStone. GemStone currently only uses the decimalPoint setting, to provide localized reading and writing of numbers involving decimal points. Updates to Locale are stored in session state, and only persist for the lifetime of the session. They are not affected by commit or abort.
To override the operating system locale information, use the following message:
Locale class >> setCategory: categorySymbol locale: LocaleString
Note that the LocaleString passed to setCategory:locale: must be defined on the host machine. If the given locale is not found, this method will return nil. You can use the UNIX command locale -a to get a list of all available LocaleStrings. To check the decimal point, the following method returns the decimalPoint setting for the current Locale:
Locale decimalPoint
%
,
While there are a number of Locale category symbols, the only ones that are of use in this release are #LC_NUMERIC and #LC_ALL, either of which will set the category that affects the decimal point.
For example, To use decimal localization appropriate for Germany:
Locale setCategory: #LC_NUMERIC locale: 'de_DE'.
To reset to UNIX default value, using period:
Locale setCategory: #LC_ALL locale: 'C'.
Note that Smalltalk syntax requires the use of “.” as the decimal point separator, so expressions involving literal floating point numbers within Smalltalk code require use of the period, regardless of Locale.
Smalltalk code that includes literal floating point values with a comma separator will fail to compile, regardless of the Locale settings.
In order to be able to export and input numerical values regardless of the Locale of a particular session, methods whose printed form includes the decimal point provide the following set of methods:
(instance method) asStringLocaleC
(class method) fromStringLocaleC:
These methods use a period as a decimal separator, regardless of the current Locale.
Universally unique identifiers (UUIDs) provide a practically unique 128-bit number that does not rely on a registry or a shared resource. UUIDs are generated randomly using the secure OpenSSL random number generator.
The class GsUuidV4 implements a version 4 UUID as specified in RFC 4122, A Universally Unique IDentifier (UUID) URN Namespace.
Instances of GsUuidV4 are invariant and cannot be modified.
To create an instance of UUID:
GsUuidV4 class >> fromString: aUuidString
aUuidString must be a valid UUID version 4 string in the following format:
xxxxxxxx-xxxx-4xxx-Vxxx-xxxxxxxxxxxx
where x is any valid lower-case hex digit and V is one of 8, 9, a or b.
The class Random and its subclasses provide random number generation.
There are two types of random number generation, which correspond to separate subclass hierarchies. The SeededRandom subclasses provide random numbers generated within GemStone code, using a starting seed value. The HostRandom subclass provides access to the host operating system’s /dev/urandom random number generator.
The class hierarchy of the Random classes are:
Object
Random (abstract)
HostRandom
SeededRandom (abstract)
Lag1MwcRandom
Lag25000CmwcRandom
The Random class is an abstract superclass for the random number generators. It also can be used to create an instance of a default random number generator class.
Random new will return an instance of HostRandom, the most basic kind of generator based on host OS /dev/urandom.
Random seed: will return an instance of Lag1MwcRandom. HostRandom does not support seeds.
While an instance of Lag25000CmwcRandom takes some time to create, it can produce a more fair and longer-period series of random numbers that are generated much more quickly than is done by the other Random subclasses.
Once you have an instance of a concrete subclass of Random, you can generate random numbers or collections of random numbers with the following range and type specifications:
float - a random Float in the range [0,1)
floats: n - a collection of n random floats in the range [0,1)
integer - a random non-negative 32-bit integer, in the range [0,232-1]
integers: n - a collection of n random non-negative integers in the range [0,232-1]
integerBetween: l and: h - a random integer in the range [l,h]. l and h should be less than approximately 231.
integers: n between: l and: h - a collection of n random integers in the range [l,h]. l and h should be less than approximately 231.
smallInteger - Answer a random integer in the SmallInteger range,
[-260,260-1]
Subsequent calls to the same instance will generate new random numbers.
You should create an instance of a Random subclass and retain that to generate many random numbers, rather than creating new instances of a Random subclass.
HostRandom allows access to the host operating system's /dev/urandom random number generator.
HostRandom is much slower to generate numbers than the other subclasses of Random, but does not have the overhead of creating an instance. On some platforms, /dev/urandom may be intended to be a cryptographically secure random number generator, which none of the other subclasses are. It also has the advantage of not needing an initial seed, and so is good for generating random seeds for other Random subclasses.
HostRandom uses a shared singleton instance, which is accessed by sending #new to the class HostRandom. Sending #new has the side effect of opening the underlying file /dev/urandom. This file normally remains open for the life of the session, but if you wish to close it you can send #close to the instance, and later send #open to reopen it. If you store a persistent reference to the singleton instance the underlying file will not be open in a new session and you must send #open to the instance before asking for a random number.
Since HostRandom is a service from the operating system, it cannot be seeded, and should not be used when a repeatable random sequence of numbers is needed.
SeededRandom is an abstract superclass for classes that generate sequences of random numbers that can be generated repeatedly by giving the same initial seed to the generator.
In addition to creating new instances using the class methods new and seed:, the following instance methods allow repeatable sequences to be generated:
seed: aSmallInteger
Sets the seed of the receiver from the given seed, which can be any SmallInteger. The subsequent random number sequence generated will be the same as if this generator had been created with this seed.
fullState, fullState: stateArray
The internal state of a generator is more than can be represented by a single SmallInteger. These messages allow you to retrieve the full state of a generator at any time, and to restore that state later. The random number sequence generated after the restoration of the state will be the same as that generated after the retrieval of the state. You might, for instance, allow a generator to get its initial state from /dev/urandom, then save this state so the random sequence can be repeated later.
Lag1MwcRandom is faster to create than Lag25000CmwcRandom, since it can be seeded by a single 61-bit SmallInteger, rather than a seed of more than 800000 bits as required by Lag25000CmwcRandom. After creation, however, it is slower, and it is not perfectly fair, and has a shorter period. It can be used when a small number of seeded random numbers are needed.
Lag25000CmwcRandom is a seedable random generator with a period of over 10240833. It is a lag-25000 generator using the complementary multiply-with-carry algorithm to generate random numbers. Its period is so long that every possible sequence of 24994 successive 32-bit integers appears somewhere in its output, making it suitable for generating random n-tuples where n<24994. Its output is fair in that the number of 0 bits and 1 bits in the full sequence are equal.
While this generator is recommended for most uses, it is not cryptographically secure, so for applications such as key generation you should consider using HostRandom, once you satisfy yourself that HostRandom is secure enough on your operating system.
You can also allow the seed bits to be initialized from the HostRandom, then retrieve that state by sending #fullState. That state can later be restored by sending the retrieved state as an argument to #fullState:.