简体   繁体   English

while 循环中的 C++ 浮点精度

[英]C++ floating point accuracy in while loops

I am trying to count the amount of dollar and coin denominations in a grand total by using a series of while loops.我试图通过使用一系列 while 循环来计算总计中美元和硬币面额的数量。 When I get down to the coins however, I am off by a penny.然而,当我深入到硬币上时,我差了一分钱。 When I enter say 99.95, I get the output 3 quarters, 1 dime, 1 nickel, and 4 pennies.当我输入 99.95 时,我会得到 3 个四分之三、1 角钱、1 镍和 4 便士的输出。 I've narrowed the problem down to a floating point accuracy issue.我已将问题缩小到浮点精度问题。 However all the solutions I've researched haven't been applicable in my situation.但是,我研究过的所有解决方案都不适用于我的情况。 Any pointers?任何指针?

#include <iostream>
using namespace std;

int main()

{
   float amount;
   cout<<"enter amount" << endl;
   cin>>amount;
   int pennies=0, nickels=0, dimes=0, quarters=0, ones=0, fives=0, 
tens=0, 
twenties=0, fifties=0, hundreds=0;

   while (amount >= 100) 
   {
      hundreds = hundreds +1;
      amount = amount - 100;

   }
   while (amount >= 50)
   {
      fifties = fifties +1;
      amount = amount - 50;

   }
   while (amount >= 20)
   {
      twenties = twenties +1;
      amount = amount - 20;

   }
   while (amount >= 10)
   {
      tens = tens +1;
      amount = amount - 10;

   }
   while (amount >= 5)
   {
      fives = fives +1;
      amount = amount - 5;

   }
   while (amount >= 1)
   {
      ones = ones +1;
      amount = amount - 1;

   }
   while (amount >= .25)
   {
      quarters = quarters +1;
      amount = amount - .25;

   }
   while (amount >= .10)
   {
      dimes = dimes +1;
      amount = amount - .10;

   }
   while (amount >= .05)
   {
      nickels = nickels +1;
      amount = amount - .05;

   }
   while (amount >= .01)
   {
      pennies = pennies +1;
      amount = amount - .01;

   }


   cout<<endl<<"pennies:"<< pennies;
   cout<<endl<<"nickels:"<<nickels;
   cout<<endl<<"dimes:"<<dimes;
   cout<<endl<<"quarters:"<<quarters;
   cout<<endl<<"ones:"<<ones;
   cout<<endl<<"fives:"<<fives;
   cout<<endl<<"tens:"<<tens;
   cout<<endl<<"twenties:"<<twenties;
   cout<<endl<<"fifties:"<<fifties;
   cout<<endl<<"hundreds:"<<hundreds<<endl;







return 0;
}

Don't use floating point in cases where you need exact values.在需要精确值的情况下不要使用浮点数。 99.95 can't be exactly represented in a float or double, a bit like 1/3 can't be exactly represented using a finite number of normal decimal digits. 99.95 不能用浮点数或双精度数精确表示,有点像 1/3 不能用有限数量的正常十进制数字精确表示。

As Doug T. suggested, you can use an integer to hold the number of pennies.正如 Doug T. 所建议的,您可以使用一个整数来表示便士的数量。 When the user types 123.45, read it as two integers, and then store it as 12345 pennies, not as 123.45 dollars.当用户键入 123.45 时,将其读为两个整数,然后将其存储为 12345 便士,而不是 123.45 美元。

In this case, you can also try to change your last while (amount >= .01) to something like while (amount >= .005) .在这种情况下,您还可以尝试将上次while (amount >= .01)更改为while (amount >= .005) It's not a solution that can be generally recommended, and if this is a real-life bank application you really should avoid it, but it will help against at least some of the errors.这不是一个普遍推荐的解决方案,如果这是一个真实的银行应用程序,你真的应该避免它,但它至少有助于防止一些错误。

You should be using fixed-point values in this case, not floating-point.在这种情况下,您应该使用定点值,而不是浮点值。

Although people think of money in terms of dollars, which aren't exact, money is measured in cents, which are exact.尽管人们以美元来看待金钱,这并不准确,但金钱以美分来衡量,这是准确的。 Just count the number of cents, divide by 100 to get the dollar amount, and take the modulus to get the cent amount.只需计算美分的数量,除以 100 即可获得美元金额,并取模数即可获得美分金额。 Floating-point is not the proper tool in this case.在这种情况下,浮点不是合适的工具。

Binary floating point numbers cannot, in general, represent fractional decimal values, even if the total number of decimals is small.二进制浮点数通常不能表示小数部分,即使小数总数很小。 For example, 0.1 cannot be represented exactly.例如,无法准确表示0.1

To deal with exact values different approaches exist which all amount to using a different base than 2 .为了处理精确值,存在不同的方法,这些方法都相当于使用与2不同的基数。 Depending on tge specific needs the approaches are more or less involved.根据 tge 的特定需求,这些方法或多或少涉及。 The easieast approach for your case is to use a fixed precision instead of a variable precision.对于您的情况,最简单的方法是使用固定精度而不是可变精度。 To compute with fixed precision you'd just use an integer which represents the value you actually want multiplied by a suitable power of 10 .要以固定精度进行计算,您只需使用一个整数来表示您实际想要的值乘以合适的10幂。 Depending on the amount of computations you do you can either package the logic into a class or distribute it throughout the code.根据您执行的计算量,您可以将逻辑打包到一个类中或将其分发到整个代码中。 In a "real" application I'd package it into a class, in an assignment (homework, interview, etc.) I'd probably just apply the logic directly to an int .在“真正的”应用程序中,我会将它打包到一个类中,在作业(家庭作业、面试等)中,我可能只是将逻辑直接应用于int

Here's the fixed code, I used TJD's advice and instead of using .01 i used .0099 instead.这是固定代码,我使用了 TJD 的建议,而不是使用 .01,而是使用了 .0099。 For my problem that seems to work, thanks guys!对于我的问题似乎有效,谢谢大家!

    #include <iostream>
using namespace std;

int main()

{
   float amount;
   cout<<"enter amount" << endl;
   cin>>amount;
   int pennies=0, nickels=0, dimes=0, quarters=0, ones=0, fives=0, 
tens=0, 
twenties=0, fifties=0, hundreds=0;
   float p = .0099, n = .0499, d = .099, q = .2499;   
   while (amount >= 100) 
   {
      hundreds = hundreds +1;
      amount = amount - 100;

   }
   while (amount >= 50)
   {
      fifties = fifties +1;
      amount = amount - 50;

   }
   while (amount >= 20)
   {
      twenties = twenties +1;
      amount = amount - 20;

   }
   while (amount >= 10)
   {
      tens = tens +1;
      amount = amount - 10;

   }
   while (amount >= 5)
   {
      fives = fives +1;
      amount = amount - 5;

   }
   while (amount >= 1)
   {
      ones = ones +1;
      amount = amount - 1;

   }
   while (amount >= q)
   {
      quarters = quarters +1;
      amount = amount - q;

   }
   while (amount >= d)
   {
      dimes = dimes +1;
      amount = amount - d;

   }
   while (amount >= n)
   {
      nickels = nickels +1;
      amount = amount - n;

   }
   while (amount >= p)
   {
      pennies = pennies +1;
      amount = amount - p;

   }


   cout<<endl<<"pennies:"<< pennies;
   cout<<endl<<"nickels:"<<nickels;
   cout<<endl<<"dimes:"<<dimes;
   cout<<endl<<"quarters:"<<quarters;
   cout<<endl<<"ones:"<<ones;
   cout<<endl<<"fives:"<<fives;
   cout<<endl<<"tens:"<<tens;
   cout<<endl<<"twenties:"<<twenties;
   cout<<endl<<"fifties:"<<fifties;
   cout<<endl<<"hundreds:"<<hundreds<<endl;







return 0;
}

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

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