Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的脚本未正确添加浮动_C_While Loop_Floating Point - Fatal编程技术网

C中的脚本未正确添加浮动

C中的脚本未正确添加浮动,c,while-loop,floating-point,C,While Loop,Floating Point,这是我第一次在这里发帖,所以这篇帖子可能有点乱,但我会尽力解释一切 我必须做一个程序,它的行为有点像商店里的自助结账。 然而,当人们把钱插入机器时,我遇到了两个问题。 人们像这样插入钱: 10 20 50 0.10 .... 付款以0或ctrl+d结束。 人们只能使用这种价值的硬币:100、50、20、10、5、2、1、0.50、0.20、0.10、0.05、0.02和0.01,正如你在代码中看到的那样 当我以0结束付款时,程序正常退出。像这样:50 20 0 然而,当我用ctrl+d结束它

这是我第一次在这里发帖,所以这篇帖子可能有点乱,但我会尽力解释一切

我必须做一个程序,它的行为有点像商店里的自助结账。 然而,当人们把钱插入机器时,我遇到了两个问题。 人们像这样插入钱: 10 20 50 0.10 .... 付款以0或ctrl+d结束。 人们只能使用这种价值的硬币:100、50、20、10、5、2、1、0.50、0.20、0.10、0.05、0.02和0.01,正如你在代码中看到的那样

当我以0结束付款时,程序正常退出。像这样:50 20 0

然而,当我用ctrl+d结束它时,它会导致无限循环,我不明白为什么

第二个问题是,出于某种原因,它不会添加0.10、0.20等数字。有没有办法解决这个问题,或者是什么原因导致了这个错误

不要介意中间的PrpTf,那只是我在检查值。

float bill,x,payment=0,k=0;



printf("coins ");
while(k==0)
{
    scanf("%f", &x);
    if(x==0 )
    {
        goto END;
    }

    if(x ==100 || x ==50 || x ==20 || x ==10 || x ==5 || x ==2 || x ==1 || x ==0.50 || x==0.10 || x ==0.20 || x ==0.05 || x ==0.02|| x ==0.01 )
        {   
            payment += x;
            printf("==============");
            printf("%.2f  \n",payment);
        }

    else{
        printf("%.2f is invalid",x);
        k = 1;      
        goto END2;
    }
}
END:
printf("%.2f  \n", payment);

END2:
return 0;
当您在终端中发送Ctrl+D时,您将EOF字符注册到stdin,因此scanf将不再读取任何内容,并且x将永远不会被设置为0,因此您将不会退出循环

您需要检查scanf的结果,读取man scanf您可以看到,如果成功,您希望返回值大于0

if (scanf("%f", &x) < 1 || x = 0) // Check return value of scanf, then check x
    GOTO: END;
编辑: 请注意,如果scanf正在读取输入项,则需要检查scanf的返回值是否不小于输入项的数量。

当您在终端中发送Ctrl+D时,您将向stdin注册一个EOF字符,因此scanf将不再读取任何内容,并且x将永远不会设置为0,因此您不会跳出循环

您需要检查scanf的结果,读取man scanf您可以看到,如果成功,您希望返回值大于0

if (scanf("%f", &x) < 1 || x = 0) // Check return value of scanf, then check x
    GOTO: END;
编辑: 请注意,如果scanf正在读取输入项,则需要检查scanf的返回值是否不小于输入项的数量。

根据hyde和alamit的评论修复此答案

您的程序拒绝添加0.10这样的小数字的原因是因为您的变量x和十进制文字(如0.10)的比较结果不同

因此,要解决此问题,请将f添加到值x==0.10f,或者切换到使用double并使用%lf读取和打印

如果你想知道问题背后的数学原理,请阅读。

根据海德和阿拉米特的评论修正这个答案

您的程序拒绝添加0.10这样的小数字的原因是因为您的变量x和十进制文字(如0.10)的比较结果不同

因此,要解决此问题,请将f添加到值x==0.10f,或者切换到使用double并使用%lf读取和打印


如果你想知道问题背后的数学原理,请阅读。

在与浮点数进行比较时,一定要小心。0.1的浮点表示形式在32位和64位浮点与双精度之间有所不同。您已经将x定义为float,这与0.1相比是double。因此,比较将无法正常工作。您必须将x定义为double,并且在代码中不做任何更改,或者将x==0.1改为x==0.1f


有关此主题的更多信息,请参见。在与浮点数进行比较时,必须小心。0.1的浮点表示形式在32位和64位浮点与双精度之间有所不同。您已经将x定义为float,这与0.1相比是double。因此,比较将无法正常工作。您必须将x定义为double,并且在代码中不做任何更改,或者将x==0.1改为x==0.1f


可以找到有关此主题的更多信息,并且

您应该检查scanf的返回值,特别是如果你想用CTRL+D.来结束它的时候,我想指出的是“BBYZ”,SCANF函数会失败,而你不考虑它。你最好把钱放在硬币上,而不是用浮点作为分数。是的,可以说。除非你有意想让舍入误差相加到可见的数值,否则千万不要使用浮点数进行货币计算。…@hyde:首先,在包括英特尔和IBM在内的硬件和包括微软在内的软件中,都有十进制浮点数格式,完全适合进行本问题中所示的货币计算。因此,在这一点上,永远不要对货币使用浮点的建议是错误的。第二,浮点格式,无论是二进制还是十进制,都适用于金融计算,如股票市场期权评估、正确设计的抵押贷款计算,甚至在正确完成时计算销售税。您应该检查scanf的返回值,特别是如果你想用CTRL+D.来结束它,我想指出的是“BBYZ”,SCANF函数会失败,而你不考虑它。你最好把钱放在硬币上,而不是用浮点作为分数。
是的,可以这么说,除非你有意想让舍入误差加起来等于可见的金额,否则千万不要用浮点数来表示货币,在包括英特尔和IBM在内的硬件和包括微软在内的软件中都有十进制浮点格式,它们非常适合进行本问题中所示的货币计算。因此,在这一点上,永远不要对货币使用浮点的建议是错误的。第二,浮点格式,无论是二进制还是十进制,都适用于金融计算,如股票市场期权评估、正确设计的抵押贷款计算,甚至在正确执行时计算销售税。如果您有读取错误,这也适用;通过检查END和perror上是否设置了errno,您可能会非常喜欢它;通过检查errno是否设置在END和perror上,您可以真正获得想象力。这和浮点的精度无关。0.1不能用二进制小数精确表示,同样的,1/3不能用10进制小数表示,它变为0.33。。。。使用double看起来只会有帮助,但实际上没有。@hyde那么为什么它与double一起工作呢?我知道范围比较<>推荐用于浮点运算,但对于这个练习来说似乎有些过头了。我用double编译并运行了代码,它通过了if条件。你知道为什么吗?这个问题来自于比较float和double,double没有相同的精度,因此不会为重复的二进制数(如0.1)存储相同的结果。例如,若要与浮点型文字OP进行比较,应使用0.1f。@谢谢,我忘记了十进制文字的C默认值为double。如果同时具有浮点型和double型两种匹配类型,则0.1解析为0.1解析为0.1。但它不会等于0.1十进制,因为float和double都没有0.1十进制的位模式。如果不想将变量类型更改为double,则可以通过比较1.0f将相等比较更改为使用float,并且对于适当定义的功值,它将再次起作用。这与float的精度无关。0.1不能用二进制小数精确表示,同样的,1/3不能用10进制小数表示,它变为0.33。。。。使用double看起来只会有帮助,但实际上没有。@hyde那么为什么它与double一起工作呢?我知道范围比较<>推荐用于浮点运算,但对于这个练习来说似乎有些过头了。我用double编译并运行了代码,它通过了if条件。你知道为什么吗?这个问题来自于比较float和double,double没有相同的精度,因此不会为重复的二进制数(如0.1)存储相同的结果。例如,若要与浮点型文字OP进行比较,应使用0.1f。@谢谢,我忘记了十进制文字的C默认值为double。如果同时具有浮点型和double型两种匹配类型,则0.1解析为0.1解析为0.1。但它不会等于0.1十进制,因为float和double都没有0.1十进制的位模式。如果不想将变量类型更改为double,则可以将相等比较更改为使用float,方法是将其与1.0f进行比较,并且对于适当定义的功值,它将再次起作用。