# DEC64: String Functions

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`

## 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.

## Creation

`dec64_string_state dec64_string_begin()`

`dec64_string_begin` creates a state object. The object should be passed to all of the other functions.

## Destruction

```void dec64_string_end(
dec64_string_state state
)```

`dec64_string_end` destroys and deallocates a state object.

## Configuration

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.

## Action

```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.

## Examples

 ```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();` ` `