One of the most difficult problems in floating-point systems is the conversion of numbers to text. This conversion is important because humans generally cannot use binary representations, and there are not simple, exact transformations between familiar decimal representations and binary floating-point. It can be difficult and expensive to find representations that are accurate, minimal, and unsurprising.
0.1 + 0.2 |
10 / 3 |
10.1 - 9.93 |
|
---|---|---|---|
IEEE754 | 0.30000000000000004 |
3.3333333333333335 |
0.16999999999999993 |
DEC64 |
0.3 |
3.3333333333333333 |
0.17 |
One of DEC64'
s advantages is that it easily and
accurately converts to decimal representations, requiring only slightly
more effort than the conversion of integers.
dec64_string.c contains functions for converting
DEC64
numbers to strings and back again.
dec64_string.h includes C function prototypes for these functions:
dec64 dec64_from_string( dec64_string_state state, dec64_string_char string[] )
dec64_string_state dec64_string_begin()
dec64_string_char dec64_string_decimal_point( dec64_string_state state, dec64_string_char decimal_point )
void dec64_string_end( dec64_string_state state )
void dec64_string_engineering( dec64_string_state state )
int dec64_string_places( dec64_string_state state, dec64_string_char places )
void dec64_string_scientific( dec64_string_state state )
int dec64_string_separation( dec64_string_state state, int separation )
dec64_string_char dec64_string_separator( dec64_string_state state, dec64_string_char separator )
void dec64_string_standard( dec64_string_state state )
int dec64_to_string( dec64_string_state state, dec64 number, dec64_string_char string[] )
Two types are provided:
dec64_string_char
dec64_string_state
The functions are reentrant and thread safe. This is accomplished by use of
a state object that is created by
dec64_string_begin
and
destroyed by dec64_string_end
.
All of the other functions require a state object as the first argument. The
state argument allows for customizing the conversions. Do not attempt to
modify the string state object directly. Use the provided functions instead.
State objects are reusable.
The state object contains the output mode: standard, scientific, or engineering.
dec64_string_state dec64_string_begin()
dec64_string_begin
creates a state object. The object should be
passed to all of the other functions.
void dec64_string_end( dec64_string_state state )
dec64_string_end
destroys and deallocates a state object.
The following functions configure or customize a state object.
void dec64_string_standard( dec64_string_state state )
Put dec64_to_string
into standard
mode. Separators can be inserted between some digits if requested. If the
number might be too long, then scientific mode might be used instead.
Standard mode is the default.
void dec64_string_scientific( dec64_string_state state )
Put dec64_to_string
into scientific mode, in which the coefficient is
displayed with one digit before the decimal point, and an exponent prefixed
with 'e'
is appended if necessary.
void dec64_string_engineering( dec64_string_state state )
Put dec64_to_string
into
engineering mode, which is like scientific mode except that the exponent is
constrained to be a multiple of 3. There can be up to three digits before
the decimal point.
dec64_string_char dec64_string_decimal_point( dec64_string_state state, dec64_string_char decimal_point )
Specify the decimal point character. This is used by both
dec64_to_string
and
dec64_from_string
.
The default is '.'
period. If it is '\0'
nul, then the
decimal point will be suppressed.
It returns the previous value.
int dec64_string_places( dec64_string_state state, dec64_string_char places )
Specify the minimum number of decimal places output by
dec64_to_string
in standard
mode. This is commonly used to format money values. The default is
0
.
It returns the previous value.
dec64_string_char dec64_string_separator( dec64_string_state state, dec64_string_char separator )
Specify the separation character, which is used by
dec64_to_string
in standard
mode to improve the readability of digits before the decimal point. Typical
values include
','
comma
' '
space
'_'
underbar
'.'
period
'\0'
nul
If it is '\0'
nul, then separation will be
suppressed. The default is '\0'
nul.
dec64_from_string
will ignore
this character.
It returns the previous value.
int dec64_string_separation( dec64_string_state state, int separation )
Specify the number of digits output between separators by
dec64_to_string
in standard
mode. If separation is 1
or less, then separation is
suppressed. The default is 3
.
It returns the previous value.
dec64 dec64_from_string( dec64_string_state state, dec64_string_char string[] )
dec64_from_string
converts a zero-delimited string into a dec64
. Separator
characters will be ignored. If conversion is not possible for any reason,
the result will be DEC64_NAN
.
int dec64_to_string( dec64_string_state state, dec64 number, dec64_string_char string[] )
dec64_to_string
converts a dec64
number into a
string. The caller provides the memory into which to deposit the string. The
provided string must have sufficient capacity to hold 32 characters. It
returns the number of characters actually deposited in the string (not
including the trailing '\0'
). If the number is nan,
then it returns 0
indicating an empty string. If
NULL
is passed in as the string, then no characters will be
deposited, but a character count will be returned.
In standard mode, the number will be formatted conventionally unless it would require more than 17 digits, which would be due to excessive trailing zeros or zeros immediately after the decimal point. In that case scientific notation will be used instead.
dec64_string_state state = dec64_string_begin(); dec64_to_string(state, dec64_new(10, -128), string); |
"1e-127" |
dec64_to_string(state, dec64_new(1024, 0), string); |
"1024" |
dec64_separator(state, ','); dec64_to_string(state, dec64_new(1024, 0), string); |
"1,024" |
dec64_separator(state, ' '); dec64_to_string(state, dec64_new(1024, 0), string); |
"1 024" |
dec64_places(state, 4); dec64_to_string(state, dec64_new(1024, 0), string); |
"1 024.0000" |
dec64_scientific(state); dec64_to_string(state, dec64_new(1024, 0), string); |
"1.024e3" |
dec64_from_string(state, "1 024.0000") |
1024 |
dec64_from_string(state, "1,024.0000") |
DEC64_NAN |
dec64_separator(state, ','); dec64_from_string(state, "1,024.0000") |
1024 |
dec64_string_end(); |