_BitInt - C23 内置高精度

· · 个人记录

是的,我知道你不是很想点进来。

但是 C 语言还活着。

C23

前往此处了解 C23 的最新进展。

_BitInt 是 C23 的特性之一,在这里可以了解各编译器的支持情况

GCC

实际上,GCC 14.1 才支持 C23 的部分特性,点击这里获取 Windows 上优秀的 GCC 移植 MinGW-w64。(由于大部分 MinGW 下载源为 GitHub,所以会出现无法下载的情况。)

_BitInt

正片开始?

C23 引入了新的整数类型 - _BitInt(n)

_BitInt(n)(亦可用作 signed _BitInt(n)),位精确的有符号整数类型(其中 n 由代表精确宽度(包括符号位)的整数常量表达式替换,它不能大于 <limits.h> 中的 BITINT_MAXWIDTHunsigned _BitInt(n),位精确的无符号整数类型(其中 n 由代表精确宽度的整数常量表达式替换,它不能大于 <limits.h> 中的 BITINT_MAXWIDTH

用法

定义

__BitInt(N) x;

x 为变量名,N 是自己定义的常数。

使用

__BitInt 支持 + - * / 等基本运算,实际上你可以当作至支持 C 的 __int128 扩展。

下面的程序输出了 _BitInt(65535) 的最大值(2^{65534} - 1),实际上在配置 GCC 14.1 的 MinGW 中,BITINT_MAXWIDTH = 65535,这意味着即使还有一位,你也只能使用 65535 位。

#include<stdio.h>
#include<string.h>
char *s[16] = { "0000", "0001", "0010", "0011",
                "0100", "0101", "0110", "0111",
                "1000", "1001", "1010", "1011",
                "1100", "1101", "1110", "1111"};
void printbin(void *p, size_t sz) {
    if(sz == 0)
        return ;
    printbin(p + 1, sz - 1);
    printf("%s%s ", s[(*(char*)p >> 4) & 15], s[*(char*)p & 15]);
}
void print0x(void *p, size_t sz) {
    while(sz --)
        printf("%02hhX ", *(char *)(p ++));
    printf("\n");
}
int cnt = 0;
#define BT 65535
#define getprint(x) void print##x(unsigned _BitInt(x) t, _Bool tg) {\
    if(t < 0) putchar('-'), t = -t;\
    if(tg && t == (unsigned _BitInt(65535))0){\
        printf("0");\
        return;\
    }\
    else if(t == (unsigned _BitInt(65535))0)\
        return ;\
    cnt ++;\
    print##x(t / 10, (unsigned _BitInt(65535))0);\
    putchar(t % 10 + '0');\
}
getprint(65535);
char zero[80000];
signed main() {
    unsigned _BitInt(65535) x = ((unsigned _BitInt(65535))1) << 65534 ;x --;
    print65535(x, 1);
}

高精!

或许你已经注意到了,_BitInt 支持恐怖的范围!实际上,2^{65534} - 1 达到了 10 ^ {19727}

可惜的是,在目前所有 OJ 上都没有 C23 与 GCC 14 编译器,这个只能用来造数据。

注意

当位数不是 8 的倍数时,高位的溢出会产生不可预料的结果(反正内存一样,为什么不开到 8 的倍数呢?)。

由于正常人不会在这种地方用 FFT,所以 n 位的乘法是 O(\frac{n^2}{64}) 的,注意时间(根据实验,GCC 似乎会把高位的 0 忽略而加快运算速度)。

C 语言总能整出神秘的东西。

\textrm{return 0;}