我写了这段代码作为一个问题的解决方案,但在一个尝试大数字作为输入的测试用例(例如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:我将它提交给网站编译器,因此无法安装任何外部库。
答案 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;
}