C 处理大输入

C Handling Large Inputs

我在 C++ 部分看到了很多这方面的问题。他们中的大多数人建议使用 uint64_t, unsigned long long 我已经尝试过

我将输入 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

此方法适用于较小的值。但不使用更大的输入

live demo

#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") 就足够了。


编辑

  1. 由于我的回答显然不够好,这里有一些说明,由于第 32 行,您在打印时得到了垃圾值:

    printf("Right Now In %"PRIu64,"\n",testNumber);
    

    PRIu64 后有一个逗号,将其删除,所有值都将正确打印。前提是你因为其他原因(比如无限循环)没有得到 RTE。

  2. 关于代码的问题(来自 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;
}