2010-09-29 164 views
2

我想知道什麼算法排序可以用來採取類似「4.72」變成了浮點數據類型,等於字符串浮動轉換?

float x = 4.72; 
+7

你真的想要一個*算法*,或者只是一個已經寫好的函數嗎? – fennec 2010-09-29 20:10:33

回答

10

scanf,operator>> istreams,而strtof將是明顯的選擇。

atof,但是,像atoi,它沒有辦法告訴你有輸入錯誤,所以一般情況下最好是避免兩者。

+0

「strtof」的+1。 – 2010-09-29 20:34:28

0

的ATOF()函數會很有幫助。 http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

+0

我強烈建議''strtod()'over atof()',因爲當你用'strtod()'得到意外的輸入時,你有更好的機會發現出了什麼問題。 – RBerteig 2010-09-29 23:36:44

+0

這是完全正確的。我同意。 – 2010-09-30 13:19:47

3

Cstrtod()C99朋友strtof()strtold()(在相同的鏈接說明)已經有一個算法來實現。

如果您在編寫自己的過程中遇到問題,請發佈您的代碼和關於它的特定問題。

+0

'strtof'而不是'strtod',因爲提問者想要一個'float'而不是'double'。 – 2010-09-29 20:35:34

+0

右斯蒂芬,謝謝(但strtof和strtold是「新」)。發佈編輯。 – pmg 2010-09-29 20:41:06

+0

使用'strtod'並將結果轉換爲'float'(隱式或轉換)與strtof'一樣好,並且更便於移植。 – 2010-09-29 21:00:02

10

對於C++,你可以使用boost::lexical_cast

std::string str("4.72"); 
    float x = boost::lexical_cast<float>(str); 

對於C,你可以使用的sscanf:

char str[]= "4.72"; 
    float x; 
    sscanf(str, "%f", &x); 
3

對於C++這是我使用的算法:

bool FromString(const string& str, double& number) { 

    std::istringstream i(str); 

    if (!(i >> number)) { 
     // Number conversion failed 
     return false; 
    } 

    return true; 
} 

我在過去使用atof()進行轉換,但是我發現這個問題很嚴重,因爲如果沒有有效的轉換,它會返回(0.0)。所以,你不知道它是否失敗並返回零,或者如果字符串實際上有「0」。

0

cplusplus.com:「stringstream提供了一個操作字符串的接口,就好像它們是輸入/輸出流一樣。」

可以初始化你的字符串stringstream然後閱讀使用operator>>stringstream的浮動,就像你會與cin

下面是一個例子:

#include<iostream> 
#include<string> 
#include<sstream> 
using namespace std; 

int main() { 
    string s = "4.72"; 
    stringstream sstrm(s); 
    float x; 
    sstrm >> x; 
    cout << x << endl; 
} 
1

我假設你想要一個實際的算法,而不是庫函數已經這樣做了。我沒有時間來編寫和測試實際的代碼,但這裏是我會做什麼:

  1. 初始化將被用作累加器0
  2. 想出一個浮在小數位在字符串中,這會讓你知道每個數字的「列」是什麼(即100s,10s,1s,1/10s等)。
  3. 從字符串的開頭開始。
  4. 取這個數字,轉換爲一個int(通過從ASCII值中減去0x30來完成)
  5. 乘以place列的值(對於示例中的第一個數字,即4 * 1 == 4 ,下一個數字7 * 0.1 == 0.7)。
  6. 將結果添加到累加器中
  7. 對每個剩餘數字從第4步開始重複。
  8. 累加器現在包含您的結果。

由於在此循環的每次迭代中基數10和基數2之間的轉換舍入,因此您從該算法得到的結果可能不是最接近原始值的二進制表示。雖然......我可能不知道改進它的好方法,但也許別人可以用這種方法加以改進。

+2

不要忘記處理像'-1.2e-3'這樣的數字。這種轉換充滿了微妙和邊緣情況。絕不容易得到正確的答案。如果你必須自己實現它,在每個你可以想象的邊緣情況下測試它的廢話。然後擔心。不要忘記NaN和INF案例。 – RBerteig 2010-09-29 20:53:57

+1

@Rerteig:如果這是我的字符串轉換函數,我可以簡單地聲明負數和科學記數法是無效的;)但是的確,是的,它需要比我寫的更復雜。我想OP只是試圖包裝是圍繞如何轉換是可能的。 – rmeador 2010-09-29 22:15:26

+0

當然,您可以決定爲了簡化問題而應該處理的內容的合理範圍。我只是想添加提醒,即將文本轉換爲浮點可能需要處理比「4.72」更復雜的情況。例如,我見過的符合C89的'strtod()'的一個實現是大約80行密集且幾乎不被評論的代碼。 – RBerteig 2010-09-29 23:27:04

3

按照您的要求爲算法,而不是一個方法,這裏是我的一個簡單的算法解釋(和C中的實現):對於點前值

  1. 初始化4整型變量,一個,一個用於後面的部分,一個用於尾數的功能,另一個用於標誌。比方說,f,m,d,sign = 1.
  2. 先看+或 - 號開頭。如果沒有符號字符或+符號,則繼續。如果第一個字符是 - ,那麼sign = -1。
  3. 然後,讀取一個整數值爲f,直到a。或NULL字符。
  4. 如果最後出現一個點字符,則開始將尾數部分與上一步一樣讀入m。但這一次也乘以每個數字乘以10。
  5. 最後,返回符號*(f +(float)m/d)。該投射確保劃分在浮點上完成,並且表達式的類型爲浮點型。

我想,閱讀代碼可能會更容易。所以這裏是代碼:

float atof(char *s) 
{ 
    int f, m, sign, d=1; 
    f = m = 0; 

    sign = (s[0] == '-') ? -1 : 1; 
    if (s[0] == '-' || s[0] == '+') s++; 

    for (; *s != '.' && *s; s++) { 
      f = (*s-'0') + f*10; 
    } 
    if (*s == '.') 
      for (++s; *s; s++) { 
        m = (*s-'0') + m*10; 
        d *= 10; 
      } 
    return sign*(f + (float)m/d); 
} 
+0

簡單的部分來源的好和清晰的解釋。不要忘記處理'-1e-6','.3e + 5','+ 2.e-4'等等,或者明確指出你不允許這種形式。考慮更好地處理格式錯誤的數字(嘗試使用「ABC」作爲輸入)。另請考慮處理NaN和INF。 C99要求'scanf()'能夠正確地恢復由'printf()'打印的值,甚至包括NaN和INF。 C89沒有,但是它的'strtod()'確實處理了'E'表示法。 – RBerteig 2010-09-29 23:33:40