Search code examples
binarydecimalstorageinformixexponent

What is the excess-65 exponent format?


According to the IBM Informix docs:

DECIMAL(p, s) values are stored internally with the first byte representing a sign bit and a 7-bit exponent in excess-65 format.

How does the "excess-65" format work?

References

  1. DECIMAL(p,s) Data Types
  2. DECIMAL Storage

Solution

  • The notation is specific to Informix and its DECIMAL and MONEY types — AFAIK, no other product uses it. Informix also uses it within its DATETIME and INTERVAL types, but that's an implementation detail for the most part.

    I've always know the on-disk form as 'excess-64' rather than 'excess-65'; I'm not sure which is correct, but I think 64 has a solid basis.

    The 'excess-6n' form is used for disk storage. It has the benefit that two decimal values in the disk format can be compared using memcmp() to get a correct comparison (though NULL values have to be handled separately — NULL values always cause pain and grief).

    The decimal.h header from ESQL/C (and C-ISAM) contains the information:

    /*
     * Packed Format  (format in records in files)
     *
     *    First byte =
     *        top 1 bit = sign 0=neg, 1=pos
     *        low 7 bits = Exponent in excess 64 format
     *    Rest of bytes = base 100 digits in 100 complement format
     *    Notes --  This format sorts numerically with just a
     *              simple byte by byte unsigned comparison.
     *              Zero is represented as 80,00,00,... (hex).
     *              Negative numbers have the exponent complemented
     *              and the base 100 digits in 100's complement
     */
    

    Note the mention of 64 rather than 65. Also note that 'decimal' is in some respects a misnomer; the data is represented using a 'centesimal' (base-100) notation.

    Here are some sample values, decimal representation and then bytes for the on-disk format. Note that to some extent, the number of bytes is arbitrary. If using something like DECIMAL(16,4), there will be 1 byte sign and exponent and 8 bytes of data (and the range of exponents will be limited). If you use DECIMAL(16) — for floating point — then the range of exponents is much less limited.

    Decimal value          Byte representation (hex)
     0                     80 00 00 00 00
     1                     C1 01
    -1                     3E 63
     9.9                   C1 09 5A 00
    -9.9                   3E 5A 0A 00
     99.99                 C1 63 63 00 00 00
    -99.99                 3E 00 01 00 00 00
     999.999               C2 09 63 63 5A
    -999.999               3D 5A 00 00 0A
     0.1                   C0 0A 00 00
    -0.1                   3F 5A 00 00
     0.00012345            BF 01 17 2D 00
    -0.00012345            40 62 4C 37 00
     1.2345678901234e-09   BC 0C 22 38 4E 5A 0C 22
    -1.2345678901234e-09   43 57 41 2B 15 09 57 42
     1.2345678901234e+09   C5 0C 22 38 4E 5A 0C 22
    -1.2345678901234e+09   3A 57 41 2B 15 09 57 42
    

    And so on.