简体   繁体   English

While循环会忽略比较两个浮点变量的布尔表达式

[英]While loop ignores a boolean expression which compares two floating point variables

Edit: 编辑:
I solved the issue by first multiplying the float value by 100, then rounding it with roundf() function, then casting it to an integer to be stored in an integer variable. 我先将浮点值乘以100,然后用roundf()函数将其舍入,然后将其roundf()转换为要存储在整数变量中的整数,从而解决了该问题。 I did the remaining operations with integer values from there on and everything worked. 我从那里开始使用整数值进行其余操作,一切正常。 Even though the solution offered by @JacobBoertjes actually worked, my assignment requiered me to use get_float() from the cs50.h library, so I didn't implement it. 即使通过@JacobBoertjes提供的解决实际工作,我的任务我需要选用使用get_float()cs50.h库,所以我并没有实现它。 Here's the final code: 这是最终代码:

// Get user input as a positive float value
float f_change;
do {
    printf("Change owed: ");
    f_change = get_float();
} while(f_change < 0);

// Round & cast
int int_change = (int) roundf(f_change * 100);

My program accepts an amount of money, say $4.20, and figures out the least amount of coins with which it can represent this value. 我的程序接受一定数量的货币,例如$ 4.20,并找出能代表该值的最小数量的硬币。 For example, desired output from the program with $4.20 as an input would be: 16 quarters ($4.00), 2 dimes ($0.20). 例如,从程序中以$ 4.20作为输入的期望输出将是:16个季度($ 4.00),2个角钱($ 0.20)。

My program successfully calculates the number of quarters, but fails to do so while working on dimes. 我的程序成功地计算了四分之一的数量,但是在处理角点数时却没有这样做。 The cause of this failure is the second for loop in the code. 失败的原因是代码中的第二个for循环 0.10 >= 0.10 does not evaluate to true, so the last iteration of the loop never happens. 0.10> = 0.10的计算结果不为true,因此循环的最后一次迭代永远不会发生。 What am I doing wrong? 我究竟做错了什么?

Here is the code. 这是代码。 I provided test print statements with their outputs written as comments. 我提供了测试打印语句,并将其输出写为注释。

#include <stdio.h>
#include <cs50.h>

int main(void) {

  // Fake user input
  float owed_coin = 4.2f;

  // Initialize coin variables
  int coin_count = 0;

  float quarters = 0.25f,
        dimes = 0.10f;

  // Calculate quarters
  while(owed_coin >= quarters) {
    owed_coin -= quarters;
    coin_count += 1;
  }
  printf("owed_coin: %.2f\ncoin_count: %d\n\n", owed_coin, coin_count);
  // Prints  owed_coin: 0.20
  //         coin_count: 16

  // Calculate dimes
  while(owed_coin >= dimes) {
    owed_coin -= dimes;
    coin_count += 1;
  }
  printf("owed_coin: %.2f\ncoin_count: %d\n\n", owed_coin, coin_count);
  // Prints  owed_coin: 0.10
  //         coin_count: 17

} }

Floating point comparison is generally a bad idea because floats often become non-exact and thus will not be exactly equal. 浮点比较通常不是一个好主意,因为浮点数经常变得不精确,因此将不完全相等。 As @bruceg mentioned, a good solution is to keep your monetary values in terms of cents, so that you avoid using a float. 如@bruceg所述,一个好的解决方案是将货币价值保持为美分,这样就避免使用浮点数。

You could replace float owed_coin = 4.2f; 您可以替换float owed_coin = 4.2f; with int owed_coin = 420; int owed_coin = 420;

In terms of gathering user input into this number, here is my suggestion using scanf 在收集用户输入此号码方面,这是我使用scanf建议

int n1, n2;

printf("Please enter amount:");
scanf("%d.%2d", &n1, &n2);

owed_coin = n1*100 + n2;

Another solution allows you you keep your variables as floats, and just compare for a very small difference between the two. 另一种解决方案使您可以将变量保持为浮点数,并且只需比较两者之间的很小差异即可。 It can be found here: What's wrong with using == to compare floats in Java? 可以在这里找到: 使用==比较Java中的浮点数有什么问题?

It uses the Java Math library, but a similar solution could look something like this in C: 它使用Java Math库,但是类似的解决方案在C语言中可能看起来像这样:

while((owed_coin - dimes) >= -0.001) {
    owed_coin -= dimes;
    coin_count += 1;
}

If you want to learn more about why floating point numbers suffer small innacuracies then check this out: https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems 如果您想更多地了解为什么浮点数会遭受小的利润,请查看以下内容: https : //en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM