将 u16string 转换为 float

Convert u16string to float

我有一个utf16编码的字符串,我想把它转换成浮点数

例如
如果有一个像 u"1342.223" 这样的 utf16 字符串,它应该 return 1342.223 浮点数,如果它是 utf8 我曾经使用 stod 函数转换它,但是如何在utf16 编码字符串 std::u16string

没有这方面的标准功能。如果您可以在恰好使用 16bit 宽字符的系统上使用 std::wstring,则可以使用:

double d;
std::wistringstream(L"1342.223") >> d;

否则,您可以利用数字从 UTF-16ASCII/UTF-8 的简单转换来编写快速转换函数。它并不理想,但应该相当有效:

double u16stod(std::u16string const& u16s)
{
    char buf[std::numeric_limits<double>::max_digits10 + 1];

    std::transform(std::begin(u16s), std::end(u16s), buf,
        [](char16_t c){ return char(c); });

    buf[u16s.size()] = '[=11=]'; // terminator

    // some error checking here?
    return std::strtod(buf, NULL);
}

如果您确实知道您的字符串是 nicely-formatted(例如没有空格),并且 当且仅当性能至关重要时(即如果您解析数百万或数十亿个数字),不要排除自己解码的可能性,循环遍历字符串。查找标准库源代码(也许比较 libc++ 和 libstdc++)以查看它们的作用,并对其进行调整。当然,在这些情况下,您还应该注意并行化您的工作,尝试利用 SIMD 等。

首先,将 utf16 numeric 字符串转换为窄字符串是微不足道的。即使您不能确定窄字符集是否为 7 位字符的 ASCII,C 也保证代码“0”到“9”应该是连续的,对于 Unicode(0x30 到 0x39)也是如此。所以代码可以很简单(仅取决于 <string> 包含:

double u16strtod(const std::u16string& u16) {
    char *beg = new char[u16.size() + 1];
    char *str = beg;
    for (char16_t uc: u16) {
        if (uc == u' ') *str++ = ' ';     // special processing for possible . and space
        else if (uc == u'.') *str++ = '.';
        else if ((uc < u'0') || (uc > u'9')) break;  // could use better error processing
        else {
            *str++ = '0' + (uc - u'0');
        }
    }
    *str++ = '[=10=]';
    char *end;
    double d = strtod(beg, &end);   // could use better error processing
    delete[] beg;
    return d;
}    

如果narrow charset是ASCII就更简单了:

double u16strtod(const std::u16string& u16) {
    char *beg = new char[u16.size() + 1];
    char *str = beg;
    for (char16_t uc: u16) {
        if ((uc <= 0) || (uc >= 127)) break;  // can only contain ASCII characters
        else {
            *str++ = uc;      // and the unicode code IS the ASCII code
        }
    }
    *str++ = '[=11=]';
    char *end;
    double d = strtod(beg, &end);
    delete[] beg;
    return d;
}