在C中处理大量的代码片段

时间:2018-03-27 23:45:39

标签: c gcc biginteger bignum

我写了这段代码作为一个问题的解决方案,但在一个尝试大数字作为输入的测试用例(例如10000000000 10000000000 1),一个奇怪的输出出来。这是整数范围数的工作,但我怎么处理大数字的代码?

这是条件:(1≤n,m,a≤10^ 9)。

#include<stdio.h>

int main()
{
    int m, n, a;
    int count = 1;

    scanf("%d%d%d",&m,&n,&a);

    if (m%a != 0) {
        count *= ((m/a)+1);
    }
    else {
        count *= (m/a);
    }

    if (n%a != 0) {
        count *= ((n/a)+1);
    } else {
        count *= (n/a);
    }

    printf("%d",count);

    return 0;
}

您可以看到问题here

ps 1:我的编译器是GNU GCC 5.1.0。

ps 2:我将它提交给网站编译器,因此无法安装任何外部库。

3 个答案:

答案 0 :(得分:2)

如果您的数字大于64位,则必须使用像GMP这样的bignum库。在基于Debian的Linux系统上,您可以使用sudo apt-get install libgmp3-dev进行安装。然后,只需加入gmp.h并阅读the docs

代码的第一部分如下所示:

#include <stdio.h>
#include <gmp.h>

int main(void) {
    mpz_t m, n, a;
    mpz_init(m); //allocate memory for the mpz_t
    mpz_init(n);
    mpz_init(a);

    mpz_inp_str(m, stdin, 10); //variable, input stream, base
    mpz_inp_str(n, stdin, 10);
    mpz_inp_str(a, stdin, 10);

    mpz_t count;
    mpz_init_set_ui(count, 1); //count = 1

    mpz_t result;
    mpz_init(result);

    mpz_mod(result, m, a); //result = m % a
    if(mpz_cmp(result, 0) != 0) { //result == 0
        mpz_tdiv_q(result, m, a); //integer truncated division: result = m / a
        mpz_add_ui(result, result, 1); // result += 1;
        mpz_mul(count, count, result); // count *= result;
    }

    //the rest of the code 

    mpz_clear(m); //clean up
    mpz_clear(n);
    mpz_clear(a);
    mpz_clear(count);
    mpz_clear(result);

    return 0;
}

答案 1 :(得分:1)

假设您的编译器将tfe定义为具有32位存储,那么您可以处理最多int的正数。

如果您需要更进一步,例如最多2^31-1,考虑使用可以处理更大整数的(可能是无符号)类型 - 例如,如果你有C11,请参见Fixed width integer types

如果你需要无界的整数,那么问题要复杂得多。在这种情况下,您最容易做的就是使用一个库,例如比如GNU multiple precision arithmetic library

  

GMP是一个用于任意精度算术的免费库,对有符号整数,有理数和浮点数进行操作。精度没有实际限制,除了机器GMP中可用内存所暗示的那些限制。 GMP具有丰富的功能,并且功能具有常规接口。

答案 2 :(得分:-1)

使用long long数据类型而不是int。因为带符号的32位整数可以处理高达2^31 - 1(即 32,767 ),而unsigned int可以达到 65,535

即使整数在int范围内,在乘法时也应该在代码强制的竞赛中使用long long。有关更好的解释,请参阅示例。

Example:

m: 100000
n: 100000
a: 1
count = 1

From your code,
count *= m/a; // count *= 100000/1 = 100000
Now,
count *= n/a; // count *= 100000/1 = 10000000000(10^10);
10^10 is beyond 32 bit int range so you will get a wrong answer -_-
So use long long to avoid such overflow errors

详细了解Data Type Ranges

如果您愿意,可以减少代码长度,例如:

#include<stdio.h>
int main()
{
    long long m, n, a, count1 = 1, count2 = 1;
    scanf("%lld%lld%lld",&m,&n,&a);
    count1 *= (m/a);
    count2 *= (n/a);
    if (m%a != 0) count1++;
    if (n%a != 0) count2++;
    printf("%lld", count1*count2);
    return 0;
}