C 处理大输入
C Handling Large Inputs
我在 C++ 部分看到了很多这方面的问题。他们中的大多数人建议使用 uint64_t, unsigned long long
我已经尝试过
- 长长
- unsigned long long
- uint64_t
我将输入 10^18 作为其最大输入。
但是正在处理的数字作为一些垃圾值返回。
我给它输入 111111111111111110
,
在我将它除以 10^(step-1)
并乘以 10^(step-1)
的那一行
该值似乎在
上下波动
Right Now In 111111111111111103
Right Now In 111111111111111104 //But it should be 111111111111111100 and then -- to decreas one more
此方法适用于较小的值。但不使用更大的输入
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<math.h>
#include<stdint.h>
#include<inttypes.h>
int step = 0;
bool isTidy(uint64_t n){
step++;
if(n < 10) return true;
int lastNumber = n % 10;
int secondLastNumber = ((n - lastNumber)/10) % 10;
return (lastNumber >= secondLastNumber) && isTidy((n - lastNumber)/10);
}
int main(){
char* inputString;
uint64_t testNumber;
int numberOfTestcases;
int iterator = 1;
scanf("%d", &numberOfTestcases);
while(numberOfTestcases --> 0){
scanf("%"SCNu64,&testNumber);
do{
step = 0;
if(isTidy(testNumber)){
printf("Case #%d: %"PRIu64"\n",iterator++, testNumber);
break;
}
printf("Right Now In %"PRIu64"\n",testNumber);
testNumber /= pow(10,step - 1);
testNumber *= pow(10,step - 1);
printf("Right Now In %"PRIu64"\n",testNumber);
}while(testNumber --> 0);
}
return 0;
}
编辑:试图澄清问题。并修复扫描输入问题
我不明白你为什么要使用 PRIu64。
我已经从 Google CodeJam 中解决了这个问题,使用 long long 的简单 scanf("%lld") 就足够了。
编辑
由于我的回答显然不够好,这里有一些说明,由于第 32 行,您在打印时得到了垃圾值:
printf("Right Now In %"PRIu64,"\n",testNumber);
PRIu64 后有一个逗号,将其删除,所有值都将正确打印。前提是你因为其他原因(比如无限循环)没有得到 RTE。
关于代码的问题(来自 Google CodeJam),它不适用于大数字(在你的例子中是一个无限循环),因为 pow() 是一个双精度和大数字会损失很多精度,if you use your own simple pow() function,你会得到一个 AC。
第二个 scanf()
中的转换说明符错误。你应该有:
scanf("%"SCNu64,&testNumber);
此外,printf()
语句之一中有一个逗号:
printf("Right Now In %"PRIu64"\n",testNumber);
启用编译器警告以帮助捕获此类简单错误是很好的。我总是至少编译:
gcc -Wall -Wextra -Wpedantic
如果没有启用警告,发布的代码将在没有警告的情况下编译。
大输入的其他问题可以追溯到 pow()
函数,它 returns 是 double
,而不是 uint64_t
。一种解决方案是将对 pow()
的调用替换为对 returns uint64_t
的另一个函数的调用。这是一个例子,虽然这不是很长一段时间内最有效的实现:
uint64_t mypow(uint64_t base, unsigned exp)
{
uint64_t res = 1;
while (exp--) {
res *= base;
}
return res;
}
我在 C++ 部分看到了很多这方面的问题。他们中的大多数人建议使用 uint64_t, unsigned long long
我已经尝试过
- 长长
- unsigned long long
- uint64_t
我将输入 10^18 作为其最大输入。 但是正在处理的数字作为一些垃圾值返回。
我给它输入 111111111111111110
,
在我将它除以 10^(step-1)
并乘以 10^(step-1)
的那一行
该值似乎在
Right Now In 111111111111111103
Right Now In 111111111111111104 //But it should be 111111111111111100 and then -- to decreas one more
此方法适用于较小的值。但不使用更大的输入
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<math.h>
#include<stdint.h>
#include<inttypes.h>
int step = 0;
bool isTidy(uint64_t n){
step++;
if(n < 10) return true;
int lastNumber = n % 10;
int secondLastNumber = ((n - lastNumber)/10) % 10;
return (lastNumber >= secondLastNumber) && isTidy((n - lastNumber)/10);
}
int main(){
char* inputString;
uint64_t testNumber;
int numberOfTestcases;
int iterator = 1;
scanf("%d", &numberOfTestcases);
while(numberOfTestcases --> 0){
scanf("%"SCNu64,&testNumber);
do{
step = 0;
if(isTidy(testNumber)){
printf("Case #%d: %"PRIu64"\n",iterator++, testNumber);
break;
}
printf("Right Now In %"PRIu64"\n",testNumber);
testNumber /= pow(10,step - 1);
testNumber *= pow(10,step - 1);
printf("Right Now In %"PRIu64"\n",testNumber);
}while(testNumber --> 0);
}
return 0;
}
编辑:试图澄清问题。并修复扫描输入问题
我不明白你为什么要使用 PRIu64。
我已经从 Google CodeJam 中解决了这个问题,使用 long long 的简单 scanf("%lld") 就足够了。
编辑
由于我的回答显然不够好,这里有一些说明,由于第 32 行,您在打印时得到了垃圾值:
printf("Right Now In %"PRIu64,"\n",testNumber);
PRIu64 后有一个逗号,将其删除,所有值都将正确打印。前提是你因为其他原因(比如无限循环)没有得到 RTE。
关于代码的问题(来自 Google CodeJam),它不适用于大数字(在你的例子中是一个无限循环),因为 pow() 是一个双精度和大数字会损失很多精度,if you use your own simple pow() function,你会得到一个 AC。
第二个 scanf()
中的转换说明符错误。你应该有:
scanf("%"SCNu64,&testNumber);
此外,printf()
语句之一中有一个逗号:
printf("Right Now In %"PRIu64"\n",testNumber);
启用编译器警告以帮助捕获此类简单错误是很好的。我总是至少编译:
gcc -Wall -Wextra -Wpedantic
如果没有启用警告,发布的代码将在没有警告的情况下编译。
大输入的其他问题可以追溯到 pow()
函数,它 returns 是 double
,而不是 uint64_t
。一种解决方案是将对 pow()
的调用替换为对 returns uint64_t
的另一个函数的调用。这是一个例子,虽然这不是很长一段时间内最有效的实现:
uint64_t mypow(uint64_t base, unsigned exp)
{
uint64_t res = 1;
while (exp--) {
res *= base;
}
return res;
}