2014-09-04 30 views
-8

我有整數,例如1234,但實際上它的意思是123.4,所以它是十進制編碼,我應該乘以10^-1。int(實際上是十進制)到字符串(1234到「123.4」)

我怎樣才能輕鬆地將此int轉換爲字符串「123.4」?我應該有「123.4」,而不是「123.3999999」。所以我需要類似itoa但更先進。

upd by string我的意思是char數組。

+4

爲正整數,'的std :: to_string(1234/10)+ 「」 + std :: to_string(1234%10)'。對於否定,請在絕對值上進行此操作,並在前面加上'「 - 」'。 – 2014-09-04 18:52:46

+2

你嘗試了什麼,你被困在哪裏?如果我們一直要求代表1用戶,我沒有看到一個觀點,爲什麼你應該滿足這些最低限度的要求! – 2014-09-04 18:54:23

+0

@ T.C。至少使用http://www.cplusplus.com/reference/cstdlib/div/代替1234到10兩次會更好嗎? – javapowered 2014-09-04 18:58:51

回答

1

我很好奇這些轉換的相對性能,所以我用幾個方法的天真版本做了一些測試。一些注意事項和注意事項:

  • 下面的轉換代碼沒有錯誤檢查,並且沒有經過測試(即不復制/粘貼代碼)。
  • 某些方法僅適用於正整數。
  • 該方法沒有等效輸出。例如數字0-9('0.0','.0','。')和10的因子('10','10。','10 .0')。你應該確定這些情況下你想要的輸出。
  • 我會從選擇最簡單的算法開始,只有在發現需要時才進行優化。你真的需要大約一億個整數/秒的性能嗎?
  • 不幸的是,我沒有一個C++ 11編譯器來測試std::to_string()版本。

算法測試是:

string toString1 (const int a) 
{ 
    char buffer[32]; 
    string result = itoa(a, buffer, 10); 
    char lastDigit = result[result.length() - 1]; 
    result[result.length() - 1] = '.'; 
    result += lastDigit; 

    return result; 
} 

void toString1a (string& Output, const int a) 
{ 
    char buffer[32]; 
    Output = itoa(a, buffer, 10); 
    char lastDigit = Output[Output.length() - 1]; 
    Output[Output.length() - 1] = '.'; 
    Output += lastDigit; 
} 

string toString2 (const int a) { 
    float f = a * 0.1f; 
    ostringstream ss; 
    ss << f; 

    return ss.str(); 
}  

const char* toString3 (const int a) 
{ 
    static char s_buffer[32]; //Careful! 

    itoa(a, s_buffer, 10); 
    size_t len = strlen(s_buffer); 
    char lastDigit = s_buffer[len-1]; 
    s_buffer[len-1] = '.'; 
    s_buffer[len] = lastDigit; 
    s_buffer[len+1] = '\0'; 

    return s_buffer; 
}  

const char* toString4 (char* pBuffer, const int a) 
{ 
    itoa(a, pBuffer, 10); 
    size_t len = strlen(pBuffer); 
    char lastDigit = pBuffer[len-1]; 
    pBuffer[len-1] = '.'; 
    pBuffer[len] = lastDigit; 
    pBuffer[len+1] = '\0'; 

    return pBuffer; 
} 

void toString4a (char* pBuffer, const int a) 
{ 
    itoa(a, pBuffer, 10); 
    size_t len = strlen(pBuffer); 
    char lastDigit = pBuffer[len-1]; 
    pBuffer[len-1] = '.'; 
    pBuffer[len] = lastDigit; 
    pBuffer[len+1] = '\0'; 
} 

const char* toString5 (char* pBuffer, const int a) 
{ 
    snprintf(pBuffer, 16, "%.1f", a/10.0); 
    return pBuffer; 
} 

const char* toString6 (char* pBuffer, const int a) 
{ 
    snprintf(pBuffer, 16, "%d.%01d", a/10, a % 10); 
    return pBuffer; 
} 

string toString7 (const int a) 
{ 
    ostringstream stream; 
    stream << (a/10) << '.' << (a % 10); 
    return stream.str(); 
} 

string toString8 (const int a) 
{ 
    char buffer[16]; 
    string result = _itoa(a, buffer, 10); 
    result.insert(result.length()-1, 1, '.'); 
    return result; 
} 

基本基準是在100個百萬個整數(從0開始)上述方法運行。如果性能對您的情況非常重要,請爲您的確切使用情況進行簡介/基準測試。

  • toString1 = 0.64秒(itoa到字符串)
  • toString1a = 0.61秒(就地,沒有返回)
  • toString2 = 33.4秒(字符串流,哎喲!)
  • toString3 = 0.52秒(itoa ,靜態緩衝區)
  • toString4 = 0.52秒(itoa)
  • toString4a = 0。52秒(itoa,就地)
  • toString5 = 6.35秒(snprintf的,浮點)
  • toString6 = 2.29秒(的snprintf,兩個整數)
  • toString7 = 33.3秒(字符串流,兩個整數)
  • toString8 = 0.70秒(itoa和string :: insert)

哪一個「更好」取決於你的需求。就我個人而言,我會使用最簡單的流案例(toString7),除非我確定我需要其他方法的性能。

+0

怎麼樣使用'std :: string :: insert()'而不是? – 2014-09-04 23:49:06

+0

使用'string :: insert'添加'toString8()'的情況,它比直接緩衝區操作case'toString1()'慢了一點。 – uesp 2014-09-05 12:32:32

+0

很有意思,謝謝!在我的情況下,我關心性能因爲我使用這個在HFT – javapowered 2014-09-05 19:57:40

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

string toString(int a) { 
    float f = a * 0.1f; 
    ostringstream ss; 
    ss << f; 
    return ss.str(); 
} 

int main() { 
    cout << toString(101); 
    return 0; 
} 
+0

流是不可接受的慢 – javapowered 2014-09-04 19:04:36

+0

@javapowered你測量了什麼嗎?你有號碼可以分享嗎? – 2014-09-04 19:57:19

+0

不,但我90%確定使用'itoa'並插入'。'。在結果字符串將更快,無bug – javapowered 2014-09-04 20:00:33

2

如果數字超過CPU的浮點精度,則除以10會導致精度損失。相反,使用這樣的事情:

string intNumStr = itoa(intNum); 
char lastDigit = intNumStr[intNumStr.length() - 1]; 
intNumStr[intNumStr.length() - 1] = '.'; 
intNumStr += string(lastDigit); 
+0

stringstream是無法接受的慢 – javapowered 2014-09-04 19:04:20

+1

@javapowered'std :: stringstream'甚至沒有在這個答案中提到?!? – 2014-09-04 19:22:37

+0

@πάνταῥεῖ這是第一次。 – 2014-09-04 19:24:47

0

對於C++ 11你可以使用這個:

std::string toString(int i) 
{ 
    int t = abs(i); 
    return (i < 0 ? "-", "") + std::to_string(t/10) + "." + std::to_string(t % 10); 
} 

預C++ 11你可以用std::stringstreamsnprintf替換:

std::string toString(int i) 
{ 
    char buffer[128] = { '-' }; 
    int t = abs(i); 
    snprintf(buffer + 1, sizeof(buffer) - 1, "%d.%d", t/10, t % 10); 
    return std::string(i < 0 ? buffer : buffer + 1); 
} 
0
#include <sstream> 
using namespace std; 

string Decimal1ToString(int i) 
{ 
    ostringstream stream; 
    stream << (i/10) << '.' << (i % 10); 
    return stream.str(); 
} 

注意使用integer /和%。 這可以防止精確度損失。

3

轉換數量爲std::string

char buffer[12]; 
std::string s = itoa(1234, buffer, 10); 

或者:

std::string s = std::to_string(intNum); 

然後只需insert()小數字符到它:

s.insert(s.length()-1, "."); 

或者:

s.insert(s.length()-1, 1, '.'); 
+0

'itoa'寫入'char *'所以我不能調用'.length()',可能我應該調用'strlen'或類似的東西。也'插入'爲char *也沒有定義太 – javapowered 2014-09-05 07:21:31

+0

再仔細看看我的例子。'itoa()'確實將'char *'返回到正在寫入的緩衝區,但是'char *'正被分配給'std :: string',它具有'length()'和'insert() '方法。 – 2014-09-05 15:06:22

0

這是我的版本:

#include <iostream> 

int main() 
{ 
    char price[18]; 
    _itoa_s(98321, price, 10); 
    int len = strlen(price); 
    char lastDigit = price[len - 1]; 
    price[len - 1] = '.'; 
    price[len] = lastDigit; 
    price[len + 1] = 0; 

    printf(price); 

    return 0; 
}