Decimal Arithmetic Specification, version 1.70
Copyright (c) IBM Corporation, 2009. All rights reserved. ©
| 7 Apr 2009 |
[previous | contents | next]
|
This section describes miscellaneous operations on decimal numbers,
including non-numeric comparisons, sign and other manipulations, and
logical operations.
The logical operations (and, invert, or,
and xor) take logical operands, which are finite
numbers with a sign of 0, an exponent of 0, and a
coefficient whose digits must all be either 0 or 1.[1]
The length of the result will be at most precision digits
(all of which will be either 0 or 1); operands are truncated on the
left or padded with zeros on the left as necessary. The result of a
logical operation is never rounded and the only flag that
might be set is invalid-operation (set if an operand is
not a valid logical operand).
The operations described are:
Notes:
-
This section uses the simplified notation introduced in the previous
section to illustrate operations.
-
It is possible to express the results of all these operations as a
decimal number or string, but for some implementations other types may
be available and might be more efficient.[2]
If an implementation does return types which are not decimal numbers
or strings then there must also be conversion operations provided to
convert from those types to decimal values or strings, so a
wholly decimal usage is possible.
-
As in the previous section, for any examples below, the context
(where relevant) is assumed to have precision set to 9,
rounding set to round-half-up, and all
trap-enablers set to 0.
and is a logical operation which takes two logical operands
(see above).
The result is the digit-wise and of the two operands; each
digit of the result is the logical and of the corresponding digits of
the operands, aligned at the least-significant digit.
A result digit is 1 if both of the corresponding operand digits
are 1; otherwise it is 0.
Examples:
and(’0’, ’0’) ==> ’0’
and(’0’, ’1’) ==> ’0’
and(’1’, ’0’) ==> ’0’
and(’1’, ’1’) ==> ’1’
and(’1100’, ’1010’) ==> ’1000’
and(’1111’, ’10’) ==> ’10’
canonical takes one operand. The result has the same value
as the operand but always uses a canonical encoding.
The definition of canonical is implementation-defined; if
more than one internal encoding for a given NaN, Infinity, or finite
number is possible then one ‘preferred’ encoding is deemed
canonical. This operation then returns the value using that
preferred encoding.
If all possible operands have just one internal encoding each, then
canonical always returns the operand unchanged (that is, it
has the same effect as copy).
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Example:
canonical(’2.50’) ==> ’2.50’
class takes one operand. The result is an indication of the
class of the operand, where the class is one of ten
possibilities, corresponding to one of the strings "sNaN"
(signaling NaN), "NaN" (quiet NaN), "-Infinity"
(negative infinity), "-Normal" (negative normal finite
number), "-Subnormal" (negative subnormal finite
number), "-Zero" (negative zero), "+Zero"
(non-negative zero), "+Subnormal" (positive subnormal finite
number), "+Normal" (positive normal finite number),
or "+Infinity" (positive infinity).
This operation is quiet; no flags are changed in the
context.
Implementations may indicate the class using a more easily tested
representation than a string (for example, an integer or an
enumeration), but in this case a mechanism for converting that
representation to the corresponding class string listed above must be
provided.
Finite numbers can only be classified as subnormal
if the exponent range is limited (that is, there is a known value for
Emin).
In the following examples, Emin is assumed to be
–999.
Examples:
class(’Infinity’) ==> "+Infinity"
class(’1E-10’) ==> "+Normal"
class(’2.50’) ==> "+Normal"
class(’0.1E-999’) ==> "+Subnormal"
class(’0’) ==> "+Zero"
class(’-0’) ==> "-Zero"
class(’-0.1E-999’) ==> "-Subnormal"
class(’-1E-10’) ==> "-Normal"
class(’-2.50’) ==> "-Normal"
class(’-Infinity’) ==> "-Infinity"
class(’NaN’) ==> "NaN"
class(’-NaN’) ==> "NaN"
class(’sNaN’) ==> "sNaN"
Note that unlike the special values in the model, the sign of any NaN
is ignored in the classification, as required by IEEE 754.
compare-total takes two operands and compares them using
their abstract representation rather than their numerical value.
A total ordering is defined for all possible abstract
representations, as described below. If the first operand is lower
in the total order than the second operand then the result
is ’-1’, if the operands have the same abstract representation
then the result is ’0’, and if the first operand is higher in
the total order than the second operand then the result is ’1’.
The total ordering is defined as follows.
-
The following items describe the ordering for representations whose
sign is 0. If the sign is 1, the order is reversed.
A representation with a sign of 1 is always lower in the
ordering than one with a sign of 0.
-
Numbers (representations which are not NaNs) are ordered such that a
larger numerical value is higher in the ordering. If two
representations have the same numerical value then the exponent is
taken into account; larger (more positive) exponents are higher in
the ordering.
-
All quiet NaNs are higher in the total ordering than all signaling NaNs.
-
Quiet NaNs and signaling NaNs are ordered according to their
payload; a larger payload is higher in the ordering.
For example, the following values are ordered from lowest to
highest: -NaN -sNaN -Infinity -127 -1.00 -1 -0.000 -0 0 1.2300
1.23 1E+9 Infinity sNaN NaN NaN456.
Examples:
compare-total(’12.73’, ’127.9’) ==> ’-1’
compare-total(’-127’, ’12’) ==> ’-1’
compare-total(’12.30’, ’12.3’) ==> ’-1’
compare-total(’12.30’, ’12.30’) ==> ’0’
compare-total(’12.3’, ’12.300’) ==> ’1’
compare-total(’12.3’, ’NaN’) ==> ’-1’
Notes:
-
The result of compare-total is always finite, exact, and unrounded.
-
The compare operation can be used
when a numerical comparison of values is required.
compare-total-magnitude takes two operands and compares them
using their abstract representation rather than their numerical value
and with their sign ignored and assumed to be 0. The result
is identical to that obtained by using compare-total on two
operands which are the copy-abs copies of the operands to
compare-total-magnitude; that is:
compare-total-magnitude(x, y)
is given by
compare-total(copy-abs(x), copy-abs(y))
copy takes one operand. The result is a copy of the
operand. This operation is unaffected by context and is quiet –
no flags are changed in the context.
Examples:
copy(’2.1’) ==> ’2.1’
copy(’-1.00’) ==> ’-1.00’
copy-abs takes one operand. The result is a copy of the
operand with the sign set to 0.
Unlike the abs operation, this operation is
unaffected by context and is quiet – no flags are
changed in the context.
Examples:
copy-abs(’2.1’) ==> ’2.1’
copy-abs(’-100’) ==> ’100’
copy-negate takes one operand. The result is a copy of the
operand with the sign inverted (a sign of 0 becomes
1 and vice versa).
Unlike the minus operation, this operation is
unaffected by context and is quiet – no flags are
changed in the context.
Examples:
copy-negate(’101.5’) ==> ’-101.5’
copy-negate(’-101.5’) ==> ’101.5’
copy-sign takes two operands. The result is a copy of the
first operand with the sign set to be the same as the
sign of the second operand.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
copy-sign( ’1.50’, ’7.33’) ==> ’1.50’
copy-sign(’-1.50’, ’7.33’) ==> ’1.50’
copy-sign( ’1.50’, ’-7.33’) ==> ’-1.50’
copy-sign(’-1.50’, ’-7.33’) ==> ’-1.50’
invert is a logical operation which takes one logical operand
(see above).
The result is the digit-wise inversion of the
operand; each digit of the result is the inverse of the
corresponding digit of the operand.
A result digit is 1 if the corresponding operand digit
is 0; otherwise it is 0.
Examples:
invert(’0’) ==> ’111111111’
invert(’1’) ==> ’111111110’
invert(’111111111’) ==> ’0’
invert(’101010101’) ==> ’10101010’
is-canonical takes one operand. The result is 1 if
the operand is canonical; otherwise it is 0.
The definition of canonical is implementation-defined; if
more than one internal encoding for a given NaN, Infinity, or finite
number is possible then one ‘preferred’ encoding is deemed
canonical. This operation then tests whether the internal encoding is
that preferred encoding.
If all possible operands have just one internal encoding each, then
is-canonical always returns 1.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Example:
is-canonical(’2.50’) ==> ’1’
is-finite takes one operand. The result is 1 if the operand
is neither infinite nor a NaN (that is, it is a normal number, a
subnormal number, or a zero); otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-finite(’2.50’) ==> ’1’
is-finite(’-0.3’) ==> ’1’
is-finite(’0’) ==> ’1’
is-finite(’Inf’) ==> ’0’
is-finite(’NaN’) ==> ’0’
is-infinite takes one operand. The result is 1 if
the operand is an Infinity; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-infinite(’2.50’) ==> ’0’
is-infinite(’-Inf’) ==> ’1’
is-infinite(’NaN’) ==> ’0’
is-NaN takes one operand. The result is 1 if
the operand is a NaN (quiet or signaling); otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-NaN(’2.50’) ==> ’0’
is-NaN(’NaN’) ==> ’1’
is-NaN(’-sNaN’) ==> ’1’
is-normal takes one operand. The result is 1 if
the operand is a positive or negative normal
number; otherwise it is 0.
This operation is quiet; no flags are changed in the
context.
Finite numbers can only be classified as normal or
subnormal if the exponent range is limited (that is, there
is a known value for Emin); if Emin is unknown,
1 is returned. In the following examples, Emin is assumed
to be –999.
Examples:
is-normal(’2.50’) ==> ’1’
is-normal(’0.1E-999’) ==> ’0’
is-normal(’0.00’) ==> ’0’
is-normal(’-Inf’) ==> ’0’
is-normal(’NaN’) ==> ’0’
is-qNaN takes one operand. The result is 1 if
the operand is a quiet NaN; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-qNaN(’2.50’) ==> ’0’
is-qNaN(’NaN’) ==> ’1’
is-qNaN(’sNaN’) ==> ’0’
is-signed takes one operand. The result is 1 if
the sign of the operand is 1; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-signed(’2.50’) ==> ’0’
is-signed(’-12’) ==> ’1’
is-signed(’-0’) ==> ’1’
is-sNaN takes one operand. The result is 1 if
the operand is a signaling NaN; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-sNaN(’2.50’) ==> ’0’
is-sNaN(’NaN’) ==> ’0’
is-sNaN(’sNaN’) ==> ’1’
is-subnormal takes one operand. The result is 1 if
the operand is a positive or negative subnormal
number; otherwise it is 0.
This operation is quiet; no flags are changed in the
context.
Finite numbers can only be classified as normal or
subnormal if the exponent range is limited (that is, there
is a known value for Emin); if Emin is unknown,
0 is returned. In the following examples, Emin is assumed
to be –999.
Examples:
is-subnormal(’2.50’) ==> ’0’
is-subnormal(’0.1E-999’) ==> ’1’
is-subnormal(’0.00’) ==> ’0’
is-subnormal(’-Inf’) ==> ’0’
is-subnormal(’NaN’) ==> ’0’
is-zero takes one operand. The result is 1 if the operand is a
zero; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
is-zero(’0’) ==> ’1’
is-zero(’2.50’) ==> ’0’
is-zero(’-0E+2’) ==> ’1’
logb takes one operand. If the operand is a NaN then the
general arithmetic rules apply. If the operand is infinite
then +Infinity is returned. If the operand is a zero, then
–Infinity is returned and the Division by zero
exceptional condition is raised.
Otherwise, the result is the integer which is the exponent of the
magnitude of the most significant digit of the operand (as though the
operand were truncated to a single digit while maintaining the value
of that digit and without limiting the resulting exponent).
All results are exact unless an integer result does not fit in the
available precision.
Examples:
logb(’250’) ==> ’2’
logb(’2.50’) ==> ’0’
logb(’0.03’) ==> ’-2’
logb(’0’) ==> ’-Infinity’
Note: The scaleb operation can be
used to change the exponent of a number.
or is a logical operation which takes two logical operands
(see above).
The result is the digit-wise inclusive or of the two
operands; each digit of the result is the logical or of the
corresponding digits of the operands, aligned at the
least-significant digit.
A result digit is 1 if either or both of the corresponding operand digits
is 1; otherwise it is 0.
Examples:
or(’0’, ’0’) ==> ’0’
or(’0’, ’1’) ==> ’1’
or(’1’, ’0’) ==> ’1’
or(’1’, ’1’) ==> ’1’
or(’1100’, ’1010’) ==> ’1110’
or(’1110’, ’10’) ==> ’1110’
radix takes no operands. The result is the radix (base) in
which arithmetic is effected; for this specification the result will
have the value 10.[3]
Example:
radix() ==> ’10’
rotate takes two operands. The second operand must be an
integer (with an exponent of 0) in the range
–precision through precision. If the first
operand is a NaN then the general arithmetic rules apply, and if it
is infinite then the result is the Infinity unchanged.
Otherwise (the first operand is finite) the result has the same
sign and exponent as the first operand, and a
coefficient which is a rotated copy of the digits in the
coefficient of the first operand.
The number of places of rotation is taken from the absolute value of
the second operand, with the rotation being to the left if the second
operand is positive or to the right otherwise.
If the coefficient of the first operand has fewer than
precision digits, it is treated as though it were padded on
the left with zeros to length precision before the rotation.
Similarly, if the coefficient of the first operand has more than
precision digits, it is truncated on the left before use.
The only flag that might be set is
invalid-operation (set if the first operand is an sNaN or
the second is not valid).
Examples:
rotate(’34’, ’8’) ==> ’400000003’
rotate(’12’, ’9’) ==> ’12’
rotate(’123456789’, ’-2’) ==> ’891234567’
rotate(’123456789’, ’0’) ==> ’123456789’
rotate(’123456789’, ’+2’) ==> ’345678912’
The shift operation can be used to shift rather
than rotate a coefficient.
same-quantum takes two operands, and returns 1 if the two
operands have the same exponent or 0 otherwise.
The result is never affected by either the sign or the coefficient of
either operand.
If either operand is a special value, 1 is returned only if
both operands are NaNs or both are infinities.
same-quantum does not change any flags in the context.
Implementations which support the concept of a boolean type may
return true for 1 and false for 0.
Examples:
samequantum(’2.17’, ’0.001’) ==> ’0’
samequantum(’2.17’, ’0.01’) ==> ’1’
samequantum(’2.17’, ’0.1’) ==> ’0’
samequantum(’2.17’, ’1’) ==> ’0’
samequantum(’Inf’, ’-Inf’) ==> ’1’
samequantum(’NaN’, ’NaN’) ==> ’1’
scaleb takes two operands. If either operand is a NaN then
the general arithmetic rules apply. Otherwise, the second operand
must be a finite integer with an exponent of zero[4]
and in the range ±2 × (Emax +
precision) inclusive, where Emax is the
largest value that can be returned by the logb
operation at the same precision setting.[5]
(If is is not, the Invalid Operation condition is raised
and the result is NaN.)
If the first operand is infinite then that Infinity is returned,
otherwise the result is the first operand modified by adding the
value of the second operand to its exponent. The result may
Overflow or Underflow.
Examples:
scaleb(’7.50’, ’-2’) ==> ’0.0750’
scaleb(’7.50’, ’0’) ==> ’7.50’
scaleb(’7.50’, ’3’) ==> ’7.50E+3’
shift takes two operands. The second operand must be an
integer (with an exponent of 0) in the range
–precision through precision. If the first
operand is a NaN then the general arithmetic rules apply, and if it
is infinite then the result is the Infinity unchanged.
Otherwise (the first operand is finite) the result has the same
sign and exponent as the first operand, and a
coefficient which is a shifted copy of the digits in the
coefficient of the first operand. The number of places to shift is
taken from the absolute value of the second operand, with the
shift being to the left if the second operand is positive or to the
right otherwise.
Digits shifted into the coefficient are zeros.
The only flag that might be set is
invalid-operation (set if the first operand is an sNaN or
the second is not valid).
Examples:
shift(’34’, ’8’) ==> ’400000000’
shift(’12’, ’9’) ==> ’0’
shift(’123456789’, ’-2’) ==> ’1234567’
shift(’123456789’, ’0’) ==> ’123456789’
shift(’123456789’, ’+2’) ==> ’345678900’
The rotate operation can be used to rotate rather
than shift a coefficient.
xor is a logical operation which takes two logical operands
(see above).
The result is the digit-wise exclusive or of the two
operands; each digit of the result is the logical exclusive-or of the
corresponding digits of the operands, aligned at the
least-significant digit.
A result digit is 1 if one of the corresponding operand digits
is 1 and the other is 0; otherwise it is 0.
Examples:
xor(’0’, ’0’) ==> ’0’
xor(’0’, ’1’) ==> ’1’
xor(’1’, ’0’) ==> ’1’
xor(’1’, ’1’) ==> ’0’
xor(’1100’, ’1010’) ==> ’110’
xor(’1111’, ’10’) ==> ’1101’
Footnotes:
[1] |
This digit-wise representation of bits in a decimal
representation has been used since the 1950s; see, for example,
Binary and truth-function operations on a decimal computer with an
extract command, William H. Kautz, Communications of the ACM, Vol. 1
#5, pp12-13, ACM Press, May 1958.
|
[2] |
For example, the operations which test whether a value is in a
particular class might return a boolean.
|
[3] |
This might be 1E+1 in the extraordinary case of precision=1.
|
[4] |
Strictly speaking this is more restrictive that IEEE 754, which would
allow 1E+1 for the second operand; however, it is in the spirit of IEEE
754 also permitting that the second operand be specifiable as an
integer.
|
[5] |
This Emax is the same as that described in IEEE 754.
|
[previous | contents | next]