Decimal floating point

Last updated

Decimal floating-point (DFP) arithmetic refers to both a representation and operations on decimal floating-point numbers. Working directly with decimal (base-10) fractions can avoid the rounding errors that otherwise typically occur when converting between decimal fractions (common in human-entered data, such as measurements or financial information) and binary (base-2) fractions.

Contents

The advantage of decimal floating-point representation over decimal fixed-point and integer representation is that it supports a much wider range of values. For example, while a fixed-point representation that allocates 8 decimal digits and 2 decimal places can represent the numbers 123456.78, 8765.43, 123.00, and so on, a floating-point representation with 8 decimal digits could also represent 1.2345678, 1234567.8, 0.000012345678, 12345678000000000, and so on. This wider range can dramatically slow the accumulation of rounding errors during successive calculations; for example, the Kahan summation algorithm can be used in floating point to add many numbers with no asymptotic accumulation of rounding error.

Implementations

Early mechanical uses of decimal floating point are evident in the abacus, slide rule, the Smallwood calculator, and some other calculators that support entries in scientific notation. In the case of the mechanical calculators, the exponent is often treated as side information that is accounted for separately.

The IBM 650 computer supported an 8-digit decimal floating-point format in 1953. [1] The otherwise binary Wang VS machine supported a 64-bit decimal floating-point format in 1977. [2] The floating-point support library for the Motorola 68040 processor provided a 96-bit decimal floating-point storage format in 1990. [2]

Some computer languages have implementations of decimal floating-point arithmetic, including PL/I, C#, Java with BigDecimal, emacs with calc, and Python's decimal module. In 1987, the IEEE released IEEE 854, a standard for computing with decimal floating point, which lacked a specification for how floating-point data should be encoded for interchange with other systems. This was subsequently addressed in IEEE 754-2008, which standardized the encoding of decimal floating-point data, albeit with two different alternative methods.

IBM POWER6 and newer POWER processors include DFP in hardware, as does the IBM System z9 [3] (and later zSeries machines). SilMinds offers SilAx, a configurable vector DFP coprocessor. [4] IEEE 754-2008 defines this in more detail. Fujitsu also has 64-bit Sparc processors with DFP in hardware. [5] [2]

Microsoft C#, or .NET, uses System.Decimal. [6]

IEEE 754-2008 encoding

The IEEE 754-2008 standard defines 32-, 64- and 128-bit decimal floating-point representations. Like the binary floating-point formats, the number is divided into a sign, an exponent, and a significand. Unlike binary floating-point, numbers are not necessarily normalized; values with few significant digits have multiple possible representations: 1×102=0.1×103=0.01×104, etc. When the significand is zero, the exponent can be any value at all.

IEEE 754-2008 decimal floating-point formats
decimal32 decimal64 decimal128 decimal(32k)Format
1111Sign field (bits)
5555Combination field (bits)
6812w = 2×k + 4Exponent continuation field (bits)
2050110t = 30×k−10Coefficient continuation field (bits)
326412832×kTotal size (bits)
71634p = 3×t/10+1 = 9×k−2Coefficient size (decimal digits)
192768122883×2w = 48×4kExponent range
963846144Emax = 3×2w−1Largest value is 9.99...×10Emax
−95−383−6143Emin = 1−EmaxSmallest normalized value is 1.00...×10Emin
−101−398−6176Etiny = 2−p−EmaxSmallest non-zero value is 1×10Etiny

The exponent ranges were chosen so that the range available to normalized values is approximately symmetrical. Since this cannot be done exactly with an even number of possible exponent values, the extra value was given to Emax.

Two different representations are defined:

Both alternatives provide exactly the same range of representable values.

The most significant two bits of the exponent are limited to the range of 0−2, and the most significant 4 bits of the significand are limited to the range of 0−9. The 30 possible combinations are encoded in a 5-bit field, along with special forms for infinity and NaN.

If the most significant 4 bits of the significand are between 0 and 7, the encoded value begins as follows:

s 00mmm xxx   Exponent begins with 00, significand with 0mmm s 01mmm xxx   Exponent begins with 01, significand with 0mmm s 10mmm xxx   Exponent begins with 10, significand with 0mmm

If the leading 4 bits of the significand are binary 1000 or 1001 (decimal 8 or 9), the number begins as follows:

s 1100m xxx   Exponent begins with 00, significand with 100m s 1101m xxx   Exponent begins with 01, significand with 100m s 1110m xxx   Exponent begins with 10, significand with 100m

The leading bit (s in the above) is a sign bit, and the following bits (xxx in the above) encode the additional exponent bits and the remainder of the most significant digit, but the details vary depending on the encoding alternative used.

The final combinations are used for infinities and NaNs, and are the same for both alternative encodings:

s 11110 x   ±Infinity (see Extended real number line) s 11111 0   quiet NaN (sign bit ignored) s 11111 1   signaling NaN (sign bit ignored)

In the latter cases, all other bits of the encoding are ignored. Thus, it is possible to initialize an array to NaNs by filling it with a single byte value.

Binary integer significand field

This format uses a binary significand from 0 to 10p−1. For example, the Decimal32 significand can be up to 107−1 = 9999999 = 98967F16 = 1001100010010110011111112. While the encoding can represent larger significands, they are illegal and the standard requires implementations to treat them as 0, if encountered on input.

As described above, the encoding varies depending on whether the most significant 4 bits of the significand are in the range 0 to 7 (00002 to 01112), or higher (10002 or 10012).

If the 2 bits after the sign bit are "00", "01", or "10", then the exponent field consists of the 8 bits following the sign bit (the 2 bits mentioned plus 6 bits of "exponent continuation field"), and the significand is the remaining 23 bits, with an implicit leading 0 bit, shown here in parentheses:

 s 00eeeeee   (0)ttt tttttttttt tttttttttt  s 01eeeeee   (0)ttt tttttttttt tttttttttt  s 10eeeeee   (0)ttt tttttttttt tttttttttt 

This includes subnormal numbers where the leading significand digit is 0.

If the 2 bits after the sign bit are "11", then the 8-bit exponent field is shifted 2 bits to the right (after both the sign bit and the "11" bits thereafter), and the represented significand is in the remaining 21 bits. In this case there is an implicit (that is, not stored) leading 3-bit sequence "100" in the true significand:

 s 1100eeeeee (100)t tttttttttt tttttttttt  s 1101eeeeee (100)t tttttttttt tttttttttt  s 1110eeeeee (100)t tttttttttt tttttttttt 

The "11" 2-bit sequence after the sign bit indicates that there is an implicit "100" 3-bit prefix to the significand.

Note that the leading bits of the significand field do not encode the most significant decimal digit; they are simply part of a larger pure-binary number. For example, a significand of 8000000 is encoded as binary 011110100001001000000000, with the leading 4 bits encoding 7; the first significand which requires a 24th bit (and thus the second encoding form) is 223 = 8388608.

In the above cases, the value represented is:

(−1)sign × 10exponent−101 × significand

Decimal64 and Decimal128 operate analogously, but with larger exponent continuation and significand fields. For Decimal128, the second encoding form is actually never used; the largest valid significand of 1034−1 = 1ED09BEAD87C0378D8E63FFFFFFFF16 can be represented in 113 bits.

Densely packed decimal significand field

In this version, the significand is stored as a series of decimal digits. The leading digit is between 0 and 9 (3 or 4 binary bits), and the rest of the significand uses the densely packed decimal (DPD) encoding.

The leading 2 bits of the exponent and the leading digit (3 or 4 bits) of the significand are combined into the five bits that follow the sign bit. This is followed by a fixed-offset exponent continuation field.

Finally, the significand continuation field made of 2, 5, or 11 10-bit declets , each encoding 3 decimal digits. [7]

If the first two bits after the sign bit are "00", "01", or "10", then those are the leading bits of the exponent, and the three bits after that are interpreted as the leading decimal digit (0 to 7): [8]

    Comb.  Exponent          Significand  s 00 TTT (00)eeeeee (0TTT)[tttttttttt][tttttttttt]  s 01 TTT (01)eeeeee (0TTT)[tttttttttt][tttttttttt]  s 10 TTT (10)eeeeee (0TTT)[tttttttttt][tttttttttt] 

If the first two bits after the sign bit are "11", then the second two bits are the leading bits of the exponent, and the last bit is prefixed with "100" to form the leading decimal digit (8 or 9):

    Comb.  Exponent          Significand  s 1100 T (00)eeeeee (100T)[tttttttttt][tttttttttt]  s 1101 T (01)eeeeee (100T)[tttttttttt][tttttttttt]  s 1110 T (10)eeeeee (100T)[tttttttttt][tttttttttt] 

The remaining two combinations (11110 and 11111) of the 5-bit field are used to represent ±infinity and NaNs, respectively.

Floating-point arithmetic operations

The usual rule for performing floating-point arithmetic is that the exact mathematical value is calculated, [9] and the result is then rounded to the nearest representable value in the specified precision. This is in fact the behavior mandated for IEEE-compliant computer hardware, under normal rounding behavior and in the absence of exceptional conditions.

For ease of presentation and understanding, 7-digit precision will be used in the examples. The fundamental principles are the same in any precision.

Addition

A simple method to add floating-point numbers is to first represent them with the same exponent. In the example below, the second number is shifted right by 3 digits. We proceed with the usual addition method:

The following example is decimal, which simply means the base is 10.

  123456.7 = 1.234567 × 105   101.7654 = 1.017654 × 102 = 0.001017654 × 105

Hence:

  123456.7 + 101.7654 = (1.234567 × 105) + (1.017654 × 102)                       = (1.234567 × 105) + (0.001017654 × 105)                       = 105 × (1.234567 + 0.001017654)                       = 105 × 1.235584654

This is nothing other than converting to scientific notation. In detail:

  e=5;  s=1.234567     (123456.7) + e=2;  s=1.017654     (101.7654)
  e=5;  s=1.234567 + e=5;  s=0.001017654  (after shifting) --------------------   e=5;  s=1.235584654  (true sum: 123558.4654)

This is the true result, the exact sum of the operands. It will be rounded to 7 digits and then normalized if necessary. The final result is:

  e=5;  s=1.235585    (final sum: 123558.5)

Note that the low 3 digits of the second operand (654) are essentially lost. This is round-off error. In extreme cases, the sum of two non-zero numbers may be equal to one of them:

  e=5;  s=1.234567 + e=−3; s=9.876543
  e=5;  s=1.234567 + e=5;  s=0.00000009876543 (after shifting) ----------------------   e=5;  s=1.23456709876543 (true sum)   e=5;  s=1.234567         (after rounding/normalization)

Another problem of loss of significance occurs when approximations to two nearly equal numbers are subtracted. In the following example e = 5; s = 1.234571 and e = 5; s = 1.234567 are approximations to the rationals 123457.1467 and 123456.659.

  e=5;  s=1.234571 − e=5;  s=1.234567 ----------------   e=5;  s=0.000004   e=−1; s=4.000000 (after rounding and normalization)

The floating-point difference is computed exactly because the numbers are close—the Sterbenz lemma guarantees this, even in case of underflow when gradual underflow is supported. Despite this, the difference of the original numbers is e = −1; s = 4.877000, which differs more than 20% from the difference e = −1; s = 4.000000 of the approximations. In extreme cases, all significant digits of precision can be lost. [10] [11] This cancellation illustrates the danger in assuming that all of the digits of a computed result are meaningful. Dealing with the consequences of these errors is a topic in numerical analysis; see also Accuracy problems.

Multiplication

To multiply, the significands are multiplied, while the exponents are added, and the result is rounded and normalized.

  e=3;  s=4.734612 × e=5;  s=5.417242 -----------------------   e=8;  s=25.648538980104 (true product)   e=8;  s=25.64854        (after rounding)   e=9;  s=2.564854        (after normalization)

Division is done similarly, but that is more complicated.

There are no cancellation or absorption problems with multiplication or division, though small errors may accumulate as operations are performed repeatedly. In practice, the way these operations are carried out in digital logic can be quite complex.

See also

Related Research Articles

<span class="mw-page-title-main">Floating-point arithmetic</span> Computer approximation for real numbers

In computing, floating-point arithmetic (FP) is arithmetic that represents a subset of real numbers using an integer with a fixed precision, called the significand, scaled by an integer exponent of a fixed base. Numbers of this form are called floating-point numbers. For example, 12.345 is a floating-point number in a base-ten representation with five digits of precision:

IEEE 754-1985 was an industry standard for representing floating-point numbers in computers, officially adopted in 1985 and superseded in 2008 by IEEE 754-2008, and then again in 2019 by minor revision IEEE 754-2019. During its 23 years, it was the most widely used format for floating-point computation. It was implemented in software, in the form of floating-point libraries, and in hardware, in the instructions of many CPUs and FPUs. The first integrated circuit to implement the draft of what was to become IEEE 754-1985 was the Intel 8087.

A computer number format is the internal representation of numeric values in digital device hardware and software, such as in programmable computers and calculators. Numerical values are stored as groupings of bits, such as bytes and words. The encoding between numerical values and bit patterns is chosen for convenience of the operation of the computer; the encoding used by the computer's instruction set generally requires conversion for external use, such as for printing and display. Different types of processors may have different internal representations of numerical values and different conventions are used for integer and real numbers. Most calculations are carried out with number formats that fit into a processor register, but some software systems allow representation of arbitrarily large numbers using multiple words of memory.

In computing, NaN, standing for Not a Number, is a particular value of a numeric data type which is undefined or unrepresentable, such as the result of zero divided by zero. Systematic use of NaNs was introduced by the IEEE 754 floating-point standard in 1985, along with the representation of other non-finite quantities such as infinities.

Double-precision floating-point format is a floating-point number format, usually occupying 64 bits in computer memory; it represents a wide dynamic range of numeric values by using a floating radix point.

In computer science, subnormal numbers are the subset of denormalized numbers that fill the underflow gap around zero in floating-point arithmetic. Any non-zero number with magnitude smaller than the smallest normal number is subnormal.

The IEEE Standard for Floating-Point Arithmetic is a technical standard for floating-point arithmetic established in 1985 by the Institute of Electrical and Electronics Engineers (IEEE). The standard addressed many problems found in the diverse floating-point implementations that made them difficult to use reliably and portably. Many hardware floating-point units use the IEEE 754 standard.

The significand is part of a number in scientific notation or in floating-point representation, consisting of its significant digits. Depending on the interpretation of the exponent, the significand may represent an integer or a fraction.

Hexadecimal floating point is a format for encoding floating-point numbers first introduced on the IBM System/360 computers, and supported on subsequent machines based on that architecture, as well as machines which were intended to be application-compatible with System/360.

Extended precision refers to floating-point number formats that provide greater precision than the basic floating-point formats. Extended precision formats support a basic format by minimizing roundoff and overflow errors in intermediate values of expressions on the base format. In contrast to extended precision, arbitrary-precision arithmetic refers to implementations of much larger numeric types using special software.

The IEEE 754-2008 standard includes decimal floating-point number formats in which the significand and the exponent can be encoded in two ways, referred to as binary encoding and decimal encoding.

IEEE 754-2008 was published in August 2008 and is a significant revision to, and replaces, the IEEE 754-1985 floating-point standard, while in 2019 it was updated with a minor revision IEEE 754-2019. The 2008 revision extended the previous standard where it was necessary, added decimal arithmetic and formats, tightened up certain areas of the original standard which were left undefined, and merged in IEEE 854.

In computing, half precision is a binary floating-point computer number format that occupies 16 bits in computer memory. It is intended for storage of floating-point values in applications where higher precision is not essential, in particular image processing and neural networks.

In computing, quadruple precision is a binary floating point–based computer number format that occupies 16 bytes with precision at least twice the 53-bit double precision.

Single-precision floating-point format is a computer number format, usually occupying 32 bits in computer memory; it represents a wide dynamic range of numeric values by using a floating radix point.

In computing, decimal32 is a decimal floating-point computer numbering format that occupies 4 bytes (32 bits) in computer memory. It is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations. Like the binary16 format, it is intended for memory saving storage.

In computing, decimal64 is a decimal floating-point computer numbering format that occupies 8 bytes in computer memory. It is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations.

decimal128 is a decimal floating-point computer number format that occupies 128 bits in computer memory. Formally introduced in IEEE 754-2008, it is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations.

In computing, octuple precision is a binary floating-point-based computer number format that occupies 32 bytes in computer memory. This 256-bit octuple precision is for applications requiring results in higher than quadruple precision. This format is rarely used and very few environments support it.

The bfloat16 floating-point format is a computer number format occupying 16 bits in computer memory; it represents a wide dynamic range of numeric values by using a floating radix point. This format is a truncated (16-bit) version of the 32-bit IEEE 754 single-precision floating-point format (binary32) with the intent of accelerating machine learning and near-sensor computing. It preserves the approximate dynamic range of 32-bit floating-point numbers by retaining 8 exponent bits, but supports only an 8-bit precision rather than the 24-bit significand of the binary32 format. More so than single-precision 32-bit floating-point numbers, bfloat16 numbers are unsuitable for integer calculations, but this is not their intended use. Bfloat16 is used to reduce the storage requirements and increase the calculation speed of machine learning algorithms.

References

  1. Beebe, Nelson H. F. (2017-08-22). "Chapter H. Historical floating-point architectures". The Mathematical-Function Computation Handbook - Programming Using the MathCW Portable Software Library (1 ed.). Salt Lake City, UT, USA: Springer International Publishing AG. p. 948. doi:10.1007/978-3-319-64110-2. ISBN   978-3-319-64109-6. LCCN   2017947446. S2CID   30244721.
  2. 1 2 3 Savard, John J. G. (2018) [2007]. "The Decimal Floating-Point Standard". quadibloc. Archived from the original on 2018-07-03. Retrieved 2018-07-16.
  3. "IBM z9 EC and z9 BC — Delivering greater value for everyone" (PDF). 306.ibm.com. Retrieved 2018-07-07.
  4. "Arithmetic IPs for Financial Applications - SilMinds". Silminds.com.
  5. "Chapter 4. Data Formats". Sparc64 X/X+ Specification. Nakahara-ku, Kawasaki, Japan. January 2015. p. 13.
  6. "Decimal floating point in .NET". Yoda.arachsys.com.
  7. Muller, Jean-Michel; Brisebarre, Nicolas; de Dinechin, Florent; Jeannerod, Claude-Pierre; Lefèvre, Vincent; Melquiond, Guillaume; Revol, Nathalie; Stehlé, Damien; Torres, Serge (2010). Handbook of Floating-Point Arithmetic (1 ed.). Birkhäuser. doi:10.1007/978-0-8176-4705-6. ISBN   978-0-8176-4704-9. LCCN   2009939668.
  8. Decimal Encoding Specification, version 1.00, from IBM
  9. Computer hardware doesn't necessarily compute the exact value; it simply has to produce the equivalent rounded result as though it had computed the infinitely precise result.
  10. Goldberg, David (March 1991). "What Every Computer Scientist Should Know About Floating-Point Arithmetic" (PDF). ACM Computing Surveys . 23 (1): 5–48. doi:10.1145/103162.103163. S2CID   222008826 . Retrieved 2016-01-20. (, , )
  11. USpatent 3037701A,Huberto M Sierra,"Floating decimal point arithmetic control means for calculator",issued 1962-06-05

Further reading