如何将大整数转换为基数 2^32?

发布于 2024-12-13 12:04:27 字数 685 浏览 0 评论 0原文

首先,我是为自己做这件事,所以请不要建议“使用 GMP / xint / bignum”(如果它适用的话)。

我正在寻找一种将大整数(例如超过 9000 位数字)转换为 232 表示形式的 int32 数组的方法。这些数字将以 10 为基数的字符串开始。

例如,如果我想将刚刚超过 INT_MAXstring a = "4294967300"(以 10 为基数)转换为新的基数 232< /sup> 数组,则为 int32_t b[] = {1,5}。如果 int32_t b[] = {3,2485738},则以 10 为基数的数字将为 3 * 2^32 + 2485738。显然,我将使用的数字甚至超出了 int64 的范围,因此我无法准确地将字符串转换为整数并修改我的成功方式。

我有一个以 10 为基数进行减法的函数。现在我想我只需执行 subtraction(char* number, "2^32") 并计算在得到 a 之前有多少次负数,但对于较大的数字可能需要很长时间。

有人可以建议一种不同的转换方法吗?谢谢。

编辑
抱歉,如果您没有看到该标签,我正在使用 C++

First off, I'm doing this for myself so please don't suggest "use GMP / xint / bignum" (if it even applies).

I'm looking for a way to convert large integers (say, OVER 9000 digits) into a int32 array of 232 representations. The numbers will start out as base 10 strings.

For example, if I wanted to convert string a = "4294967300" (in base 10), which is just over INT_MAX, to the new base 232 array, it would be int32_t b[] = {1,5}. If int32_t b[] = {3,2485738}, the base 10 number would be 3 * 2^32 + 2485738. Obviously the numbers I'll be working with are beyond the range of even int64 so I can't exactly turn the string into an integer and mod my way to success.

I have a function that does subtraction in base 10. Right now I'm thinking I'll just do subtraction(char* number, "2^32") and count how many times before I get a negative number, but that will probably take a long time for larger numbers.

Can someone suggest a different method of conversion? Thanks.

EDIT
Sorry in case you didn't see the tag, I'm working in C++

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

美男兮 2024-12-20 12:04:27

假设您的 bignum 类已经具有乘法和加法,则相当简单:

 bignum str_to_big(char* str) {
     bignum result(0);
     while (*str) {
         result *= 10;
         result += (*str - '0');
         str = str + 1;
     }
     return result;
 }

转换另一种方式是相同的概念,但需要除法和模数

std::string big_to_str(bignum num) {
    std::string result;
    do {
        result.push_back(num%10);
        num /= 10;
    } while(num > 0);
    std::reverse(result.begin(), result.end());
    return result;
}

这两者都仅适用于无符号。

Assuming your bignum class already has multiplication and addition, it's fairly simple:

 bignum str_to_big(char* str) {
     bignum result(0);
     while (*str) {
         result *= 10;
         result += (*str - '0');
         str = str + 1;
     }
     return result;
 }

Converting the other way is the same concept, but requires division and modulo

std::string big_to_str(bignum num) {
    std::string result;
    do {
        result.push_back(num%10);
        num /= 10;
    } while(num > 0);
    std::reverse(result.begin(), result.end());
    return result;
}

Both of these are for unsigned only.

皇甫轩 2024-12-20 12:04:27

要将基数为 10 的字符串转换为您的编号系统,请从零开始继续将每个基数 10 数字与 10 相加和相乘。每次有进位时,都会向基数 2^32 数组添加一个新数字。

To convert from base 10 strings to your numbering system, starting with zero continue adding and multiplying each base 10 digit by 10. Every time you have a carry add a new digit to your base 2^32 array.

往日 2024-12-20 12:04:27

最简单(不是最有效)的方法是编写两个函数,一个将一个大数乘以一个 int,另一个将一个 int 添加到一个大数。如果您忽略有符号数字引入的复杂性,代码看起来像这样:(

为了清楚起见,编辑使用向量并为实际问题添加代码)

void mulbig(vector<uint32_t> &bignum, uint16_t multiplicand)
{
    uint32_t carry=0;
    for( unsigned i=0; i<bignum.size(); i++ ) {
        uint64_t r=((uint64_t)bignum[i] * multiplicand) + carry;
        bignum[i]=(uint32_t)(r&0xffffffff);
        carry=(uint32_t)(r>>32);
    }
    if( carry )
        bignum.push_back(carry);
}

void addbig(vector<uint32_t> &bignum, uint16_t addend)
{
    uint32_t carry=addend;
    for( unsigned i=0; carry && i<bignum.size(); i++ ) {
        uint64_t r=(uint64_t)bignum[i]  + carry;
        bignum[i]=(uint32_t)(r&0xffffffff);
        carry=(uint32_t)(r>>32);
    }
    if( carry )
        bignum.push_back(carry);
}

然后,使用这些函数实现atobignum()是微不足道的:

void atobignum(const char *str,vector<uint32_t> &bignum)
{
    bignum.clear();
    bignum.push_back(0);
    while( *str ) {
        mulbig(bignum,10);
        addbig(bignum,*str-'0');
        ++str;
    }
}

The simplest (not the most efficient) way to do this is to write two functions, one to multiply a large number by an int, and one to add an int to a large number. If you ignore the complexities introduced by signed numbers, the code looks something like this:

(EDITED to use vector for clarity and to add code for actual question)

void mulbig(vector<uint32_t> &bignum, uint16_t multiplicand)
{
    uint32_t carry=0;
    for( unsigned i=0; i<bignum.size(); i++ ) {
        uint64_t r=((uint64_t)bignum[i] * multiplicand) + carry;
        bignum[i]=(uint32_t)(r&0xffffffff);
        carry=(uint32_t)(r>>32);
    }
    if( carry )
        bignum.push_back(carry);
}

void addbig(vector<uint32_t> &bignum, uint16_t addend)
{
    uint32_t carry=addend;
    for( unsigned i=0; carry && i<bignum.size(); i++ ) {
        uint64_t r=(uint64_t)bignum[i]  + carry;
        bignum[i]=(uint32_t)(r&0xffffffff);
        carry=(uint32_t)(r>>32);
    }
    if( carry )
        bignum.push_back(carry);
}

Then, implementing atobignum() using those functions is trivial:

void atobignum(const char *str,vector<uint32_t> &bignum)
{
    bignum.clear();
    bignum.push_back(0);
    while( *str ) {
        mulbig(bignum,10);
        addbig(bignum,*str-'0');
        ++str;
    }
}
拧巴小姐 2024-12-20 12:04:27

我认为Docjar:gnu/java/math/MPN.java 可能包含您要查找的内容,特别是 public static int set_str (int dest[], byte[] str, int str_len, int base) 的代码。

I think Docjar: gnu/java/math/MPN.java might contain what you're looking for, specifically the code for public static int set_str (int dest[], byte[] str, int str_len, int base).

眼前雾蒙蒙 2024-12-20 12:04:27

首先将数字转换为二进制。从右边开始,每组 32 位都是一个 base2^32 数字。

Start by converting the number to binary. Starting from the right, each group of 32 bits is a single base2^32 digit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文