将 int(实际上是十进制)转换为字符串(1234 到 "123.4")

convert int (which actually decimal) to string (1234 to "123.4")

本文关键字:1234 字符串 转换 实际上 int 十进制      更新时间:2023-10-16

我有整数,例如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::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 );
}
#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;
}