[英]Incorrect output when converting from int to float with static_cast<float> c++
我不明白为什么我的输出是错误的。 我附上了我的代码和我的结果(突出显示了问题)
我正在向 VendingMachine 类中的 insertCoin 函数添加一个硬币。 一旦我向这个函数添加 10 美分,它就会打印出错误-> 不接受 10 美分。 我正在使用 static_cast 将输入转换为浮点数。 我花了一些时间在这上面,在这一点上,我觉得我看不到这个问题,可能是因为我不明白一些概念。
也作为快速背景,C++ 新手并试图让我的面向对象编程保持最新状态。 尝试制作自动售货机产品呵呵。 再次感谢你 !
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <utility>
#include <stdlib.h>
using namespace std;
class Item
{
private:
string m_name;
float m_cost;
public:
Item(string t_name,float t_cost):m_name(t_name),m_cost(t_cost)
{
}
string getName()
{
return m_name;
}
float getCost()
{
return m_cost;
}
};
class VendingMachine
{
private:
vector<Item> m_totalItems;
unordered_map<string,Item>m_products;
float m_remainingCharges{0};
float m_moneyInserted{0};
size_t itemCount{0};
public:
VendingMachine()
{
}
void addItemToVendingMachine(string t_name,size_t t_cost)
{
float temp=static_cast<float>(t_cost)/static_cast<float>(100);
Item item(t_name,temp);
m_totalItems.push_back(item);
m_products.insert(make_pair(t_name,item));
}
bool chooseProduct(string t_name)
{
for(auto item:m_totalItems)
{
if(item.getName()==t_name)
{
m_remainingCharges=item.getCost();
return true;
}
itemCount++;
}
cout<<"Item not currently available: "+t_name<<endl;
return false;
}
void insertCoin(size_t t_coin)
{
float temp=static_cast<float>(t_coin);
if(t_coin<=50)
{
temp/=100;
cout<<temp<<endl;
}
if(temp==0.01 or temp==0.05 or temp==0.1 or temp==1.00 or temp==2.00 or temp==0.25 or temp==0.50)
{
m_moneyInserted+=temp;
m_remainingCharges-=m_moneyInserted;
}
else
{
cout<<"Does not accept: "<< t_coin<<" ,please insert correct coin."<<endl;
return;
}
}
pair<Item,float> getProduct()
{
auto item=m_totalItems[itemCount];
auto itemBack=m_totalItems.back();
m_totalItems[itemCount]=itemBack;
m_totalItems.pop_back();
return make_pair(item,abs(m_remainingCharges));
}
float refund()
{
if(m_remainingCharges<0)
return abs(m_remainingCharges);
else
return 0;
}
void resetOperator()
{
m_remainingCharges=0;
m_moneyInserted=0;
itemCount=0;
}
};
int main()
{
Item item("Candy",0.50);
cout<<item.getName()<<" ";
cout<<item.getCost()<<endl;
VendingMachine machine;
machine.addItemToVendingMachine("CANDY",10);
machine.addItemToVendingMachine("SNACK",50);
machine.addItemToVendingMachine("Coke",25);
machine.insertCoin(10);
machine.insertCoin(25);
machine.insertCoin(50);
machine.chooseProduct("CANDY");
auto temp=machine.getProduct();
cout<<temp.first.getName()<<endl;
cout<<temp.second<<endl;
machine.resetOperator();
return 0;
};
这不是特定于 C++,而是特定于浮点数。
C++ 标准没有说明浮点是如何编码的。 但一般来说,浮点数是使用两个小数的幂进行编码的。 在这些方案中,一些十进制数没有精确匹配,而是使用最接近的匹配,并带有一些近似值。
例如,最流行的编码可能是IEEE-754 。 这个不错的在线转换器显示0.1
没有完全匹配。 最接近的近似值是0.100000001490116119384765625
:
==
比较相等性,则该值必须完全相同。 不幸的是,不同的计算可能会进行不同的舍入。 所以你会得到两个不同的数字,非常接近 0.1 但彼此不同。如果您不相信,请尝试以下更改:
if(t_coin<=50)
{
temp/=100;
cout.precision(10); // print more digits
cout<<scientific<<"temp:"<<temp<<" vs.double "<<0.1
<<" or float "<<0.1f<<endl;
}
然后尝试将浮点数与浮点数进行比较:
if(temp==0.01f or temp==0.05f or temp==0.1f
or temp==1.00f or temp==2.00f
or temp==0.25f or temp==0.50f)
正如有人在评论中建议的那样,这里最好的选择是使用整数并计算美分。 在这种计算中没有浮点引起的近似值,所以对于金钱来说它是理想的。
一种解决方法是将所有浮点数对齐为double
或float
(通过向数字文字添加尾随f
)。 如果在某些计算中没有舍入问题,这将在比较常量值时起作用。
另一种解决方案是替换严格相等比较,用不等式检查两个数字之间的差异是否非常小。 这是 Jason在另一个答案中提出的 epsilon 方法,在 此处解释的almost_equal()
函数的帮助下比较这些值
不相关:不要使用size_t
来表示钱。 这对读者和维护者来说是一种误导;-)。 如果你想要一个 unsigned int、一个 unsigned long 或一个 unsigned long long,就这么说。
您可以使用epsilon
来比较浮点数,克服了很难精确地相等浮点数的事实,您必须使用“非常接近等于”。 有关更多详细信息,请参阅此帖子: 浮动和双重比较的最有效方法是什么?
我个人建议将代码更改为以美分整数单位工作,以避免在整个代码中实现“非常接近”模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.