varch/doc/floatl.md
2025-03-06 01:33:43 +08:00

182 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 介绍
`floatl`为一个大型浮点数模块,该模块允许对超过 C 语言标准数据类型限制的大浮点数进行操作。它提供了一个灵活的长整型表示,使用 16 位和 32 位段来存储。
现在主流的计算机系统中一般支持的最大整形数为 32bits 或者 64bits 的,其能满足在一般情况下的计算及存储,但是面对一些更大的数时候就会显得有心无力。
而`floatl`模块作为额外的浮点数扩充,采用了与 `IEEE 754` 一致的存储机制,而且在使用起来也非常方便。提供以下的计算:
- 支持基本算术操作:加法、减法、乘法、除法。
- 将字符串和标准浮点数转换为大浮点数的功能。
- 提供以十进制、`[P-]` 和 `[E-]`格式输出大浮点数的函数。
`floatl` 可以按需配置为 64bits、128bits、256bits、512bits、1024bits、2048bits、4096bits、8192bits如果都还不满足还提供了生成更大bits的函数来生成更大的配置。
## 接口
## 结构定义
### `floatl`
一个结构体,用于表示长整型浮点数,使用联合体以两种不同方式存储浮点数:
- 一个 `uint16_t` 类型的数组16 位段)。
- 一个 `uint32_t` 类型的数组32 位段)。
```c
typedef struct {
union {
uint16_t u16[__FLOATL_U16_PARTS__]; ///< Array of uint16_t values representing the long bit integer in 16-bit segments.
uint32_t u32[__FLOATL_U32_PARTS__]; ///< Array of uint32_t values representing the long bit integer in 32-bit segments.
struct {
uint32_t mantissas[__FLOATL_MANT_PARTS__];
uint32_t mantissa : __FLOATL_MANT_HIGH_BITS__;
uint32_t exponent : __FLOATL_EXP_BITS__;
uint32_t sign : 1;
};
};
} floatl;
```
### 定义函数
```c
floatl floatl_from(const char *str);
floatl floatl_from_f(float value);
floatl floatl_from_d(double value);
```
`floatl`提供了两种定义函数。
`floatl_from`为从数字字符串中解析生成一个`floatl`,支持解析十进制、`[P-]` 和 `[E-]`格式字符串。
`floatl_from_f`为从`float`型中创建一个`floatl`。
`floatl_from_d`为从`double`型中创建一个`floatl`,此函数封装成更简短的宏定义方法`floatl()`更贴近使用习惯,此方法执行效率更高。
三者的使用,当值在`double`的取值范围内时,推荐使用`floatl()`方法,而当数值超越`double`的取值范围时或者需要不同进制进行定义时,就可以使用`floatl_from`方法。
同时,也可以使用常用值的宏定义`FLOATL_INF`、`FLOATL_NAN`、`FLOATL_CONST_0`、`FLOATL_CONST_1`、`FLOATL_CONST_10`等。
例子:
```c
static void test_define(void)
{
floatl a = floatl(0.0);
floatl b = floatl(10.0);
floatl c = floatl(-3.14);
floatl d = floatl(1.23456789e+10);
floatl e = floatl(0x1.23456789p+10);
floatl f = floatl_from("0.0");
floatl g = floatl_from("10.0");
floatl h = floatl_from("-3.14");
floatl i = floatl_from("1.23456789e+10");
floatl j = floatl_from("0x1.23456789p+10");
floatl zero = FLOATL_CONST_0;
floatl one = FLOATL_CONST_1;
floatl ten = FLOATL_CONST_10;
printf("size %d\r\n", sizeof(floatl));
}
```
### 转换函数
```c
int floatl_print(floatl a, char *buffer, uint32_t size, const char *format);
#define floatl_show(a, b, s, f) (floatl_print((a), (b), (s), (f)) > 0 ? (b) : "invalid")
```
此函数把`a`的值根据格式转换成十进制、`[P-]` 和 `[E-]`格式到传入的`buffer`中,并返回有效位的`buffer`地址。
`buffer`和`size`分别是存储转换结果的缓冲区的地址和大小
`format`使用与`printf`类似,```[flags][width][type]```,如`0.2f`、`+5.2a`等。
```c
static void test_print(void)
{
floatl a = floatl_from("1234567890.123456789");
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%f"));
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%.2f"));
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%020.2f"));
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%+.6a"));
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%+20.6a"));
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%-20.6e"));
}
```
结果:
```
a 1234567890.123451
a 1234567890.12
a 00000001234567890.12
a +0x1.26580bp+30
a +0x1.26580bp+30
a 1.234568e+009
```
### 运算函数
```c
floatl floatl_add(floatl a, floatl b); // a+b
floatl floatl_sub(floatl a, floatl b); // a-b
floatl floatl_mul(floatl a, floatl b); // a*b
floatl floatl_div(floatl a, floatl b); // a/b
floatl floatl_abs(floatl a); // |a|
floatl floatl_neg(floatl a); // -a
int floatl_eq(floatl a, floatl b); // a<b
int floatl_ne(floatl a, floatl b); // a<=b
int floatl_lt(floatl a, floatl b); // a==b
int floatl_le(floatl a, floatl b); // a!=b
int floatl_gt(floatl a, floatl b); // a>b
int floatl_ge(floatl a, floatl b); // a>=b
```
`floatl`运算函数与类似符号运算一致。
使用例子:
```c
static void test_calculate(void)
{
floatl a = floatl_from("12345678901234567890.123456789");
floatl b = floatl_from("98765432109876543210.987654321");
printf("a %s\r\n", floatl_show(a, buffer, sizeof(buffer), "%f"));
printf("b %s\r\n", floatl_show(b, buffer, sizeof(buffer), "%f"));
printf("a + b: %s\r\n", floatl_show(floatl_add(a, b), buffer, sizeof(buffer), "%f"));
printf("a - b: %s\r\n", floatl_show(floatl_sub(a, b), buffer, sizeof(buffer), "%f"));
printf("a * b: %s\r\n", floatl_show(floatl_mul(a, b), buffer, sizeof(buffer), "%f"));
printf("a / b: %s\r\n", floatl_show(floatl_div(a, b), buffer, sizeof(buffer), "%f"));
printf("-a: %s\r\n", floatl_show(floatl_neg(a), buffer, sizeof(buffer), "%f"));
printf("|a|: %s\r\n", floatl_show(floatl_abs(a), buffer, sizeof(buffer), "%f"));
printf("a > b: %d\r\n", floatl_gt(a, b));
printf("a >= b: %d\r\n", floatl_ge(a, b));
printf("a < b: %d\r\n", floatl_lt(a, b));
printf("a <= b: %d\r\n", floatl_le(a, b));
printf("a == b: %d\r\n", floatl_eq(a, b));
printf("a != b: %d\r\n", floatl_ne(a, b));
}
```
结果:
```
a 12345678901234567890.123457
b 98765432109876543210.987654
a + b: 111111111011111111101.111111
a - b: -86419753208641975320.864198
a * b: 1219326311370217952261850327336229233322.374638
a / b: 0.125000
-a: -12345678901234567890.123457
|a|: 12345678901234567890.123457
a > b: 0
a >= b: 0
a < b: 1
a <= b: 1
a == b: 0
a != b: 1
```