2

コンソールベースの電卓アプリケーションを作成しています。アプリケーションは、ユーザーのキー押下を処理して操作を実行します。整数入力は正常に機能します。ただし、ユーザーがバックスペースを押して10進数を消去する場合のコードを書く際に問題に直面しています。

小数点以下のスペースを消去するために書いたコードは次のとおりです。

decimalcount--; // number of decimal places is subtracted by 1
lnum -= fmod (lnum, pow (10, -decimalcount + 1)); // subtraction
cout << setprecision (decimalcount) << lnum << endl; // display the code

ただし、12.00400679 などの特定の数値では、値が正しく減算されていません。

12.00400679
12.00400670
12.0040060
12.004000
12.00400
12.0040
12.000
11.90
11.0
10

プログラムの完全なソースは次のとおりです。

#include <iostream>
#include <iomanip>
#include <cmath>
#include <conio.h>
using namespace std;

int sgn (double x)
{
    if (x < 0)
    {
        return -1;
    }
    return 1;
}

int main ()
{
    cout.setf (ios::fixed);

    double lnum = 0, expr = 0;
    int decimalcount = 0;
    char ch, op;

    while (true)
    {
        ch = _getch ();
        if (isdigit (ch))
        {

            if (! decimalcount)
            {
                if (sgn (lnum) == sgn (lnum * 10 + sgn (lnum) * (ch - 48)))
                {
                    lnum = lnum * 10 + sgn(lnum) * (ch - 48);
                    cout << setprecision (0) << lnum << endl;
                }
            }
            else
            {
                if (decimalcount < 9)
                {
                    lnum += sgn (lnum) * (ch - 48) * pow (10, -decimalcount);
                    cout << setprecision (decimalcount) << lnum << endl;
                    decimalcount++;
                }
            }
        }
        else if (ch == '\b')
        {

            if (! decimalcount)
            {
                lnum -= fmod (lnum, 10);
                lnum /= 10;
                cout << setprecision (0) << lnum << endl;
            }
          // This is where I am having problems
            else
            {
                decimalcount--;
                lnum -= fmod (lnum, pow (10, -decimalcount + 1));
                cout << setprecision (decimalcount) << lnum << endl;
            }
        }
        else if (ch == '.')
        {
            if (! decimalcount)
            {
                decimalcount = 1;
                cout << setprecision (decimalcount) << lnum << endl;
            }
        }
        else if (ch == 'x')
        {
            return 0;
        }
    }

}

誰かが私が間違っているところを教えてもらえますか?

前もって感謝します、

4

3 に答える 3

6

変換が早すぎます。入力中は、入力を文字列として保持し、入力が終了して計算の準備が整ったときにのみ内部形式に変換する必要があります。

しかし、あなたは物事を難しい方法で行っているようです。std::getlineonを使用 してstd::cin、受け取ったテキストを解析してみませんか? そうすれば、システムがバック スペースなどを処理するので、ユーザーが処理する必要はありません。何らかの理由でこれが受け入れられない場合でも、入力を別の関数に分解する必要があります。これは、ほぼ同じことを行います。

于 2013-02-12T09:38:20.340 に答える
2

これは、これらの値を浮動小数点数で正確に表すことができないためです。浮動小数点がメモリ内でどのように表されるかを読む価値があります。

正確な小数点以下の桁数が必要な場合は、固定小数点演算を使用した方がよい場合があります。ただし、そのような操作のために浮動小数点に変換しない限り、三角関数などを実装するのは面倒な場合があります。

于 2013-02-12T09:31:19.617 に答える
0

保持したい有効桁数が変更される可能性があるため、数値に対して算術演算を実行することは避けてください。代わりに、文字列に変換して切り捨て、実際の算術値が必要なときに元に戻すことができます。例:

double d;

// ...

std::ostringstream sstream;
sstream << d;
std::string str = sstream.str();

または:

char str[10];
snprintf(str, 10, "%g", d);

しかし、一般的には、James Kanze の回答を使用して、すべての入力を文字列として保存し、最後に数値にのみ変換します。

于 2013-02-12T09:41:26.463 に答える