C -- Double 类型数据 : Number slightly larger than allowed is able to slip through the conditions

标签 c double

我是 C 语言新手,我的学位需要完成一门 C 编程类(class)。希望标题有意义……我很难表达我的意思。我会在这里详细说明。

我现在面临的问题是双类型数据在应该被拒绝的情况下却能够在未被检测到的情况下通过程序。当提供的数字非常接近我设置的边界时,就会发生这种情况。

在这个作业中,为了获得 HD,我的代码必须具有与讲师相同的输出。该解决方案能够检测任何大于边界的数字,无论距离有多近。

基本上,程序会要求用户提供 0 到 4 之间的 GPA。 我尝试了以下输入: 4.01 拒绝 4.001 被拒绝 ... 4.000001 被拒绝 但在 4.0000001 时,它被接受。这根本不应该发生。我很困惑。

这是我的代码:

double GPA=-1; /*Flags are being initialised*/
int GPAflag=1;
while(GPAflag){
    char str[50];
    char *ptr;
    int isnum=1,n=0,i,point=0;
    printf("Enter GPA>");
    fflush(stdin);
    gets(str); 
    n = strlen(str); 
    if(n==0){ /*string length is 0? There was no input, thus invalid*/
        printf("Invalid GPA. ");
        isnum=0;
    }else{
        for(i=0;i<n;i++) /*Validates numerical inputs, if not numerical, prompts user with error*/
        if(!(str[i]>='0' && str[i]<='9')){
            if(str[i]!='.'){
                printf("Invalid GPA. ");
                isnum=0;
                break;
            }else{
                point++;
            }
        }
    }
    if(isnum){ /*If the input is a number, it may still be invalid*/
        GPA=strtod(str, &ptr); /*The string is converted to a double*/
        if(GPA>=0&&GPA<=4&&point<=1) /*If GPA is between 0 and 4, and the above is also satisfied (point=1), then the flag is 0 and thus a valid input*/
            GPAflag=0;
        else
            printf("Invalid GPA. "); /*If not, it is still invalid*/
    }
}

我个人认为这不会成为问题,但我真的很想知道为什么会发生这种情况,如果可能的话,想知道解决它的方法。

我可以简单地创建一个 FOR 循环: IF 前导数字是 4 并且有一个“.” -> 拒绝 但这对我来说似乎是硬编码,我认为这只是一种解决方法而不是实际的解决方案。 或者我可以将 IF 语句从“<=4”更改为“<4.0000000000000000000000...1”。在我看来,哪个应该失去分数...(如果我是标记者,我会为此扣分)

此外,我完全意识到函数“gets”是原始的,会导致许多问题(溢出......等)。我尝试过使用 fgets,但实现起来很痛苦...用 '\0' 替换 '\n' 等等等等...我们甚至没有学过 gets,更不用说 fgets 了。有没有更好的方法来实现fgets?也许有一个函数可以替换 '\n'?我已经尝试过,但它拒绝工作。

非常感谢任何帮助和提示!

最佳答案

OP 的真实代码使用的是 float GPA=-1;,因此 GPA=strtod("4.0000001", &ptr); 产生了 GPA由于 floatdouble 相比,精度限制更大,因此 code> 值恰好为 4.0。

通过使用double GPA;,如发布的代码中所示,GPA=strtod("4.0000001", ...GPA=strtod("4.000000001 ", ... 将返回一个略大于 4 的值。即使 GPA=strtod("4.00000000000001", ... 也可能返回一个略大于 4 的值。

在某些时候,double 的有限精度会将 GPA=strtod("4.0 muchdigits 001", ... 渲染为 4.0。限制精度的典型解决方案位数为 15 或更少。

(如果使用超过 15 个数字,可能会 mock 用户。)

关于C -- Double 类型数据 : Number slightly larger than allowed is able to slip through the conditions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37350229/

相关文章:

c - 游程代码解码中数组的奇怪行为

c - 为什么 lseek 允许我设置负文件位置?

c++ - 如何使用 cin 读取 double 的全部值?

java - 为什么 (long)9223372036854665200d 给我 9223372036854665216?

iphone - 双数据类型+iphone

java - 将数组转换为 double

c++ - 在 C++ 中混淆 "double to long long"

c - VS 2012 printf() 的舍入行为

c、导入不同行的文本文件并处理行

c - 查找数组C中的元素