3

私はルーレットのような C++ コマンドライン プログラムを書いています。ユーザーは、賭けのために小数値/数字を入力することができます。これを可能にするために double 型の変数を使用しています。しかし、たとえば 1 ドルから始めて、0.23 ドルを賭けて負け、次に 0.55 ドルを賭けて負け、0.07 ドルを賭けてまた負けた場合、実際には 0.15 ドル持っているとプログラムが主張していても、0.15 ドルを賭けることはできません。ドル (持っている以上のお金を賭けることはできません)。プログラムが間違って減算しているようです。しかし、私はまだ 0.149 ドルを賭けることができます。価値があるのは、stringstream を使用して、ユーザーの賭けの入力を double 型の値に変換することです。誰かがここで何が起こっているのか説明できますか?

これが私のコードです:

#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;
}
4

4 に答える 4

4

これは、プログラムの減算が間違っているからではありません。2 進分数と 10 進分数が「数学的に完全に互換性がある」わけではないからです。

したがって、0.15 のような一部の小数には、いくつかの有効な二重近似が存在します。減算の結果としてそのうちの 1 つが得られ (A)、文字列 "0.15" からの変換の結果として別の近似が得られます (B)。そして、たまたま B が A より大きく見えた。

正確な小数の丸めを維持するには、2 倍のドルではなく、整数のセントを使用する必要があります。より一般的な解決策は、整数を使用して小数演算を容易に実装する 10進数クラス (このような) を使用することです。

一部の 10 進数 (および 2 進数) クラスは、任意精度の算術演算を実装しています。ハードウェアでサポートされている double 型よりも大きな固定小数点部分を持つタスクを解決します。セント (小数点以下 2 桁) への丸めが規定されているアプリケーションでは、これは必要ありません。

于 2013-10-16T15:33:29.753 に答える
1

丸め誤差は、数学演算がエラーを悪化させる可能性があるため、数学を多用するプログラムで大混乱を引き起こす可能性があります。

http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/

于 2013-10-16T15:34:26.200 に答える