我正在编写类似轮盘赌的C ++命令行程序。用户可以输入用于下注的小数值/数字。我正在使用双类型变量来实现这一点。但是,如果我以1美元开始,然后输掉0.23美元,那么下注0.55美元而输,然后下注0.07美元又输了,我不能下注0.15美元,即使程序声称我实际上有0.15美元美元(你不能赌更多的钱)。看来程序错误地减少了。不过,我仍然可以下注0.149美元。为了它的价值,我使用stringstream将用户的投注输入转换为双类型值。有人能解释一下这里发生了什么吗?
这是我的代码:
#include <iostream>
#include <sstream>
using namespace std; //Std namespace.
void string_to_number(string input, double& destination);
class Roulette {
private:
int randoms;
double money, choice, bet;
string input;
public:
int play = 0;
void start_amount() {
cout<<"How much money do you have?: ";
getline(cin, input);
string_to_number(input, money);
}
void betting() {
cout<<"How much money would you like to bet?: ";
getline(cin, input);
string_to_number(input, bet);
while (bet > money) {
cout<<"You can't bet more money than you have ("<<money<<" dollars). Please enter again: ";
getline(cin, input);
string_to_number(input, bet);
}
}
void choose_number() {
cout<<"Which number do you choose? (0-35): ";
getline(cin, input);
string_to_number(input, choice);
}
void random_number() {
cout<<"The wheel is spinning..."<<endl<<flush;
randoms = (rand())%36;
}
void scenarios() {
cout<<"The wheel shows number "<<randoms;
if (randoms == choice) {
money += bet;
cout<<", which means that you win "<<bet<<" dollars! You currently have "<<money<<" dollars."<<flush<<endl;
}
else {
money -= bet;
cout<<", which means that you lose "<<bet<<" dollars. You currently have "<<money<<" dollars."<<flush<<endl;
}
}
};
int main(int argc, const char * argv[])
{
srand(unsigned(time(0)));
Roulette a;
a.start_amount();
while (a.play == 0) {
a.betting();
a.choose_number();
a.random_number();
a.scenarios();
}
return 0;
}
void string_to_number(string input, double& destination) {
stringstream convert(input);
if ( !(convert >> destination) )
destination = 0;
}
答案 0 :(得分:2)
这不是因为程序减去错误 - 这是因为二进制分数和小数分数不是“完全数学上兼容” - 有限小数分数通常是无限周期二进制分数。
因此,对于像0.15这样的一些小数部分,存在几个有效的双重近似,因为减法的结果是你得到其中一个(A),并且从字符串“0.15”转换的结果你得到另一个(B)。而事故B似乎大于A。
你应该使用整数美分而不是双美元来保持精确的十进制舍入。更一般的解决方案是使用一些十进制数类(如this),它可以使用整数轻松实现小数分数运算。
一些十进制(和二进制)数字类实现arbitrary precision arithmetic - 它解决了固定点部分大于硬件支持的双重类型的任务。在规定舍入为美分(2位小数)的应用程序中,您不需要这样做。
答案 1 :(得分:0)
舍入错误会对数学密集型程序造成严重破坏,因为数学运算可能会使错误复杂化。
http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/