将 int(实际上是十进制)转换为字符串(1234 到 "123.4")
convert int (which actually decimal) to string (1234 to "123.4")
我有整数,例如1234,但实际上它的意思是123.4,所以它是十进制编码的,我应该乘以10^-1。
如何轻松地将此int转换为字符串"123.4"?我应该有"123.4",而不是"123.3999999"。所以我需要类似itoa
但更高级的东西。
upd我指的是字符数组。
将数字转换为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, '.');
如果数字超过CPU的浮点精度,则除以10可能会导致精度损失。相反,使用这样的东西:
string intNumStr = itoa(intNum);
char lastDigit = intNumStr[intNumStr.length() - 1];
intNumStr[intNumStr.length() - 1] = '.';
intNumStr += string(lastDigit);
我对这些转换的相对性能很好奇,所以我用一些方法的幼稚版本做了一些测试。一些注意事项和注意事项:
- 以下转换代码没有错误检查,也没有经过测试(即,不要复制/粘贴代码)
- 有些方法只适用于正整数
- 这些方法没有等效的输出。例如数字0-9("0.0"、".0"、".")和因子10("10"、"10."、"10.0")。您应该确定这些情况下需要的输出
- 我会从选择最简单的算法开始,只在发现需要时进行优化。你真的需要大约1亿个整数/秒的性能吗
- 不幸的是,我没有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] = ' ';
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] = ' ';
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] = ' ';
}
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;
}
对于1亿个整数(从0开始),在上述方法上运行了基本基准测试。如果性能真的对您的用例很重要,请为您自己的确切用例进行评测/基准测试。
- toString1=0.64秒(itoa到字符串)
- toString1a=0.61秒(原地,无返回)
- toString2=33.4秒(字符串流,哎哟!)
- toString3=0.52秒(itoa,静态缓冲区)
- toString4=0.52秒(itoa)
- 至String4a=0.52秒(itoa,就地)
- toString5=6.35秒(snprintf,float)
- toString6=2.29秒(snprintf,两个整数)
- toString7=33.3秒(字符串流,两个整数)
- toString8=0.70秒(itoa和字符串::insert)
哪一个"更好"取决于你需要什么。就我个人而言,我会使用最简单的流情况(toString7),除非我绝对确定我需要其他方法的性能。
#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;
}
对于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::stringstream
或snprintf
:
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 );
}
#include <sstream>
using namespace std;
string Decimal1ToString(int i)
{
ostringstream stream;
stream << (i / 10) << '.' << (i % 10);
return stream.str();
}
请注意使用整数/和%。这样可以防止精度损失。
这是我的版本:
#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;
}