## 介绍 `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); // ab 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 ```