C++ 中两个大十六进制数的 mod [重复]

mod of two big hex numbers in c++ [duplicate]

提问人:A D 提问时间:11/12/2023 最后编辑:A D 更新时间:11/12/2023 访问量:153

问:

我有两个大的十六进制数,每个十六进制数至少有 70 位(十进制),我正在尝试计算值 hex_a%hex_b:

string hex_a="1133A5DCDEF3216A63EB879A82F5A1DC4490CCF6412492CF1B242DB";
string hex_b="AAB3A5DCDEF3216A6AAA2F5A1DC4490CCF6412492CF1B242DB";

我尝试使用 stoi 将两个十六进制数转换为十进制数并将值存储在字符串中:

string a=to_string(stoi(hex_a, 0, 16));

但是我在使用 stoi 方法时出现错误:

terminate called after throwing an instance of 'std::out_of_range'
  what():  stoi
Aborted (core dumped)

如何在 C++ 中计算两个大数的 mod?

C++ 数学 加密 数字 十六进制

评论

2赞 Sam Varshavchik 11/12/2023
你还记得你在小学时是如何学习长除法的吗?它是如何工作的?只需使用十六进制实现长除法算法即可。这就是如何做到的。
0赞 A D 11/12/2023
@SamVarshavchik是的,但我在 C++ 中存储大十进制时遇到了一个问题。哪种类型可以在 C++ 中存储 80 位的十进制数?
3赞 Pepijn Kramer 11/12/2023
诀窍是你不要将它们存储为字符串(就像你已经做的那样)并使用 carry 逐位计算。正如@SamVarshavchik所说,这就像小学一样,你一口气把大数字分了吗?还是逐个数字?严格来说,没有必要先转换为十进制(尽管有大的 int 库可用)
0赞 A D 11/12/2023
在 C++ 中,我们可以使用运算符 % 计算两个十进制数的 mod。我尝试将两个十六进制中的每一个转换为十进制,但我没有成功。
0赞 Ted Lyngmo 11/12/2023
“我尝试将两个十六进制中的每一个转换为十进制,但我没有成功” - 如果你表现出这种尝试,也许有人可以指出你做错了什么

答:

1赞 Sergey Vlasov 11/12/2023 #1

首先,你不能将这么大的数字转换为“int”、“long”、“long long”、“double”等。

第一种方法是在字符串上实现基本的数学运算(+,-,乘以 16 或移位),然后自己实现除法算法。 请参阅以下参考:https://en.wikipedia.org/wiki/Division_algorithm

第二种方法是使用 和 “任意精度算术库”:https://en.wikipedia.org/wiki/List_of_arbitrary-precision_arithmetic_software

例如 https://www.boost.org/doc/libs/1_83_0/libs/multiprecision/doc/html/index.html

1赞 Sash Sinha 11/12/2023 #2

您可以使用升压/多精度/cpp_int

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <sstream>
#include <string>

using boost::multiprecision::cpp_int;

int main() {
  std::string hex_a = "0x1133A5DCDEF3216A63EB879A82F5A1DC4490CCF6412492CF1B242DB";
  std::string hex_b = "0xAAB3A5DCDEF3216A6AAA2F5A1DC4490CCF6412492CF1B242DB";
  cpp_int a(hex_a), b(hex_b);
  cpp_int result = a % b;
  std::cout << "Result as int: " << result << '\n';
  std::stringstream ss;
  ss << std::hex << result;
  std::string result_hex = ss.str();
  std::cout << "Result as hex: 0x" << result_hex << '\n';
  return 0;
}

或者 GNU 多精度算术库 (GMP),它可能更快:

#include <gmp.h>

int main() {
  mpz_t a, b, result;
  mpz_init(a);
  mpz_init(b);
  mpz_init(result);
  mpz_set_str(a, "1133A5DCDEF3216A63EB879A82F5A1DC4490CCF6412492CF1B242DB", 16);
  mpz_set_str(b, "AAB3A5DCDEF3216A6AAA2F5A1DC4490CCF6412492CF1B242DB", 16);
  mpz_mod(result, a, b);
  gmp_printf("Result as int: %Zd\n", result);
  gmp_printf("Result as hex: Ox%Zx\n", result);
  mpz_clear(a);
  mpz_clear(b);
  mpz_clear(result);
  return 0;
}

输出:

Result as int: 887778964514700662847592530576646032246936850244260028835776
Result as hex: 0x8d6e6cdeb792c9d42b257481c738989f678484c94fd6b567c0

在 Python 中确认相同的结果:

>>> hex_a = "0x1133A5DCDEF3216A63EB879A82F5A1DC4490CCF6412492CF1B242DB"
>>> hex_b = "0xAAB3A5DCDEF3216A6AAA2F5A1DC4490CCF6412492CF1B242DB"
>>> a = int(hex_a, 16)
>>> b = int(hex_b, 16)
>>> result = a % b
>>> print(f'Result as int: {result}')
Result as int: 887778964514700662847592530576646032246936850244260028835776
>>> print(f'Result as hex: 0x{result:x}')
Result as hex: 0x8d6e6cdeb792c9d42b257481c738989f678484c94fd6b567c0

评论

1赞 A D 11/12/2023
非常感谢兄弟。欣赏它!
0赞 Mike 'Pomax' Kamermans 11/12/2023
尽管您仍然错过了退回到十六进制字符串的步骤。如果输入和输出需要十六进制,那么值得检查一下这是否比在十六进制环境中使用模数学规则计算模更快。
1赞 Sash Sinha 11/12/2023
@Mike'Pomax'Kamermans PTAL 更新:)
0赞 A D 11/12/2023
嗨,我的代码在进行 50 次计算后变慢了 4% (a%b)。这些是因为 boost 库很慢吗?还是因为与其他人相比,这些考虑了一个非常大的计算?
0赞 A D 11/12/2023
@SashSinha你能向我推荐一个比 boost/multiprecision/cpp_int 更快的库吗?