乘以非常大的十六进制数并在 C 中打印它们
Multiplying very large hex numbers and printing them in C
我想将 2 个非常大的十六进制数相乘并打印出来,例如:
28B2D48D74212E4F x 6734B42C025D5CF7 = 1068547cd3052bbe5688de35695b1239
因为我预计它是一个非常大的数字,所以我使用 unsigned long long int
输入:
unsigned long long int x = 0x28B2D48D74212E4F;
unsigned long long int y = 0x6734B42C025D5CF7;
并像这样打印乘法:
fprintf(stdout, "%llx\n", x*y);
我得到的正好是预期结果的一半:
5688de35695b1239
为什么要把它截断到一半?有没有比unsigned long long
更大的东西?
您要查找的响应不适合 64 位 unsigned long long
,这是 64 位平台上的正常大小;乘法期间的任何多余部分都会溢出并丢弃。
较新版本的 GCC 在 64 位机器 和 __int128
(和 unsigned __int128
)上支持 128 位整数 ,这有效:
unsigned long long int x = 0x28B2D48D74212E4FULL;
unsigned long long int y = 0x6734B42C025D5CF7ULL;
unsigned __int128 xy = x * (unsigned __int128)y;
请注意,您必须将 x
或 y
之一转换为更宽的类型,以便以 128 位完成乘法;否则,直到(截断的)64 位乘法之后才会提升到 128。
问题是,据我所知,printf()
没有办法轻松地做到这一点,所以你将不得不自己动手。
这里有一些合理的讨论:how to print __uint128_t number using gcc?
但这对我有用:
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
#include <stdio.h>
int main()
{
unsigned long long int x = 0x28B2D48D74212E4F;
unsigned long long int y = 0x6734B42C025D5CF7;
unsigned __int128 xy = x * (unsigned __int128)y;
printf("Result = %016llx%016llx\n",
(unsigned long long)( xy >> 64),
(unsigned long long)( xy & 0xFFFFFFFFFFFFFFFFULL));
return 0;
printf
中的转换很重要:否则 shifting/masking 是在 128 位标量中完成的,然后将这 128 位压入堆栈,但随后每个 %llx
期望64 位。
请注意,这完全取决于底层平台并且不可移植;肯定有一种方法可以使用各种#ifdefs 和 sizeofs 来使其更通用,但可能没有超级棒的方法可以使它在任何地方都有效。
我想将 2 个非常大的十六进制数相乘并打印出来,例如:
28B2D48D74212E4F x 6734B42C025D5CF7 = 1068547cd3052bbe5688de35695b1239
因为我预计它是一个非常大的数字,所以我使用 unsigned long long int
输入:
unsigned long long int x = 0x28B2D48D74212E4F;
unsigned long long int y = 0x6734B42C025D5CF7;
并像这样打印乘法:
fprintf(stdout, "%llx\n", x*y);
我得到的正好是预期结果的一半:
5688de35695b1239
为什么要把它截断到一半?有没有比unsigned long long
更大的东西?
您要查找的响应不适合 64 位 unsigned long long
,这是 64 位平台上的正常大小;乘法期间的任何多余部分都会溢出并丢弃。
较新版本的 GCC 在 64 位机器 和 __int128
(和 unsigned __int128
)上支持 128 位整数 ,这有效:
unsigned long long int x = 0x28B2D48D74212E4FULL;
unsigned long long int y = 0x6734B42C025D5CF7ULL;
unsigned __int128 xy = x * (unsigned __int128)y;
请注意,您必须将 x
或 y
之一转换为更宽的类型,以便以 128 位完成乘法;否则,直到(截断的)64 位乘法之后才会提升到 128。
问题是,据我所知,printf()
没有办法轻松地做到这一点,所以你将不得不自己动手。
这里有一些合理的讨论:how to print __uint128_t number using gcc?
但这对我有用:
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
#include <stdio.h>
int main()
{
unsigned long long int x = 0x28B2D48D74212E4F;
unsigned long long int y = 0x6734B42C025D5CF7;
unsigned __int128 xy = x * (unsigned __int128)y;
printf("Result = %016llx%016llx\n",
(unsigned long long)( xy >> 64),
(unsigned long long)( xy & 0xFFFFFFFFFFFFFFFFULL));
return 0;
printf
中的转换很重要:否则 shifting/masking 是在 128 位标量中完成的,然后将这 128 位压入堆栈,但随后每个 %llx
期望64 位。
请注意,这完全取决于底层平台并且不可移植;肯定有一种方法可以使用各种#ifdefs 和 sizeofs 来使其更通用,但可能没有超级棒的方法可以使它在任何地方都有效。