2013-02-12 59 views
2

我正在製作基於控制檯的計算器應用程序。應用程序處理用戶按鍵來執行其操作。積分輸入正常工作;然而,我正面臨編寫代碼的問題,即用戶按下退格鍵刪除十進制數的情況。刪除浮點數的最後一位數的問題

,我寫信給抹去小數位的代碼如下:

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

} 

任何人都可以告訴我我在做什麼它錯了嗎?

由於提前,

+3

您知道某些值例如「0.1」不能用二進制浮點數精確表示嗎? – PlasmaHH 2013-02-12 09:28:59

+6

我建議你閱讀[每個計算機科學家應該知道的關於浮點運算的知識](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)。 – 2013-02-12 09:30:52

+3

將輸入存儲爲字符串,而不是浮點數。在需要時將其轉換。 – Pubby 2013-02-12 09:30:56

回答

6

你轉換得太早。在輸入過程中,您應該將 輸入保留爲一個字符串,並且只有在 輸入完成時才轉換爲您的內部格式,並且您已準備好進行計算。

但是,你似乎正在努力的方式。爲什麼不在std::cin上使用 std::getline,並解析您收到的文本? 這樣,系統就可以處理背部空間之類的東西,而你不需要。如果由於某種原因,這是不可接受的,你應該仍然把輸入分解成一個單獨的函數, ,它或多或少地做了同樣的事情。

+0

我不能使用std :: cin,因爲它需要用戶按下回車鍵,這在我的程序中是不允許的。 – user2064000 2013-02-12 09:44:29

+0

@ user2064000那麼你怎麼知道你什麼時候可以開始計算?你需要某種終結者。我仍然將輸入分解爲一個單獨的函數,該函數返回一個字符串。 (當然,你可以把輸入作爲一個整數,跟蹤小數,當你準備做計算時乘以10的適當冪,但我建議使用字符串方法。) – 2013-02-12 09:56:22

+0

在實際的計算器應用程序中(上面貼出的代碼只是其中的一部分),用戶按下一個鍵:+, - ,*,/,s(sin),c(cos)等等,從而導致相關的計算。 – user2064000 2013-02-12 09:59:04

2

這是因爲這些值不能被精確由一個浮點數來表示。值得關注的是如何在內存中表示浮點。

如果您需要確切的小數位數,您最好使用定點算術。但是,實現trig函數等可能會令人討厭,除非您將這些操作轉換爲浮點。

+0

如果他需要精確的十進制算術,有實現它的庫可用。 (它也可以在'double'的基礎上實現;只需要將所有輸入的數字保持爲整數,並分別保留小數點。) – 2013-02-12 09:40:06

0

您應該避免對數字執行算術運算,因爲這可能會改變您要保留的有效數字。相反,您可以將其轉換爲字符串並截斷它,然後在需要實際算術值時將其轉換回來。例子:

double d; 

// ... 

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

或者:

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

但在一般情況下,我會與詹姆斯甘孜的答案去和存儲所有輸入字符串和僅轉換爲數值結尾。