mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
decimal format documented
This commit is contained in:
@ -107,6 +107,21 @@
|
|||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <decimal.h>
|
#include <decimal.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
|
||||||
|
So one "decimal_digit" is
|
||||||
|
|
||||||
|
0 < decimal_digit <= DIG_MAX < DIG_BASE
|
||||||
|
|
||||||
|
in the struct st_decimal:
|
||||||
|
|
||||||
|
intg is the number of *decimal* digits (NOT number of decimal_digit's !)
|
||||||
|
before the point
|
||||||
|
frac - number of decimal digits after the point
|
||||||
|
buf is an array of decimal_digit's
|
||||||
|
len is the length of buf (length of allocated space) in decimal_digit's,
|
||||||
|
not in bytes
|
||||||
|
*/
|
||||||
typedef decimal_digit dec1;
|
typedef decimal_digit dec1;
|
||||||
typedef longlong dec2;
|
typedef longlong dec2;
|
||||||
|
|
||||||
@ -1073,6 +1088,68 @@ int decimal2longlong(decimal *from, longlong *to)
|
|||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
|
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
for storage decimal numbers are converted to the "binary" format.
|
||||||
|
|
||||||
|
This format has the following properties:
|
||||||
|
1. length of the binary representation depends on the {precision, scale}
|
||||||
|
as provided by the caller and NOT on the intg/frac of the decimal to
|
||||||
|
convert.
|
||||||
|
2. binary representations of the same {precision, scale} can be compared
|
||||||
|
with memcmp - with the same result as decimal_cmp() of the original
|
||||||
|
decimals (not taking into account possible precision loss during
|
||||||
|
conversion).
|
||||||
|
|
||||||
|
This binary format is as follows:
|
||||||
|
1. First the number is converted to have a requested precision and scale.
|
||||||
|
2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
|
||||||
|
as is
|
||||||
|
3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
|
||||||
|
number of bytes (enough bytes to store this number of digits -
|
||||||
|
see dig2bytes)
|
||||||
|
4. same for frac - full decimal_digit's are stored as is,
|
||||||
|
the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
|
||||||
|
5. If the number is negative - every byte is inversed.
|
||||||
|
5. The very first bit of the resulting byte array is inverted (because
|
||||||
|
memcmp compares unsigned bytes, see property 2 above)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
1234567890.1234
|
||||||
|
|
||||||
|
internally is represented as 3 decimal_digit's
|
||||||
|
|
||||||
|
1 234567890 123400000
|
||||||
|
|
||||||
|
(assuming we want a binary representation with precision=14, scale=4)
|
||||||
|
in hex it's
|
||||||
|
|
||||||
|
00-00-00-01 0D-FB-38-D2 07-5A-EF-40
|
||||||
|
|
||||||
|
now, middle decimal_digit is full - it stores 9 decimal digits. It goes
|
||||||
|
into binary representation as is:
|
||||||
|
|
||||||
|
|
||||||
|
........... 0D-FB-38-D2 ............
|
||||||
|
|
||||||
|
First decimal_digit has only one decimal digit. We can store one digit in
|
||||||
|
one byte, no need to waste four:
|
||||||
|
|
||||||
|
01 0D-FB-38-D2 ............
|
||||||
|
|
||||||
|
now, last digit. It's 123400000. We can store 1234 in two bytes:
|
||||||
|
|
||||||
|
01 0D-FB-38-D2 04-D2
|
||||||
|
|
||||||
|
So, we've packed 12 bytes number in 7 bytes.
|
||||||
|
And now we invert the highest bit to get the final result:
|
||||||
|
|
||||||
|
81 0D FB 38 D2 04 D2
|
||||||
|
|
||||||
|
And for -1234567890.1234 it would be
|
||||||
|
|
||||||
|
7E F2 04 37 2D FB 2D
|
||||||
*/
|
*/
|
||||||
int decimal2bin(decimal *from, char *to, int precision, int frac)
|
int decimal2bin(decimal *from, char *to, int precision, int frac)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user