c - 将非常大的十六进制数相乘并在 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-bit unsigned long long
,这是 64-bit 平台上的正常大小;乘法过程中的任何多余部分都会溢出并丢弃。
较新版本的 GCC 确实支持64 位机器上的128位整数__int128
(and unsigned __int128
),这有效:
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 (红帽 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
很重要:否则移位/屏蔽是在 128 位标量中完成的,而这 128 位被推入堆栈,但每个都%llx
需要 64 位。
请注意,这完全取决于底层平台,不可移植;肯定有一种方法可以使用各种#ifdefs 和 sizeofs 使其更通用,但可能没有超级棒的方法可以让这项工作无处不在。
推荐阅读
- php - php删除空格、逗号并插入数据库
- php - 禁用 gzip 压缩(安装 ext/zlib)
- html - 我可以使用相同的复选框 hack 触发 2 个动作吗?使用 CSS
- genexus - GX 15 U6 Java - OpenAPI(重新)生成
- c# - 将动态生成的输入列表表单数据从视图传递到asp.net中的控制器
- android - 将多个参数传递给 ViewModel Primary Constructor
- javascript - 使用值创建标签的事件监听器
- java - ArrayUtils 无法解析
- javascript - 如何从 Elasticsearch 查询中的嵌套范围访问父字段?
- scala - 为什么需要模式匹配来保留存在类型信息?