0

在我的代码中,我需要将整数的字符串表示形式转换为longdouble

字符串表示是一个字节数组 ( byte[])。例如,对于数字12345字符串表示是{ 49, 50, 51, 52, 53 }

目前,我使用以下明显的代码转换为long(以及几乎相同的代码转换为double

private long bytesToIntValue()
{
    string s = System.Text.Encoding.GetEncoding("Latin1").GetString(bytes);
    return long.Parse(s, CultureInfo.InvariantCulture);
}

此代码按预期工作,但就我而言,我想要更好的东西。这是因为目前我必须先将字节转换为字符串。

在我的例子中,bytesToIntValue()被调用了大约 1200 万次,大约 25% 的内存分配是在这种方法中进行的。

当然,我想优化这部分。我想在没有中间字符串的情况下执行转换(+ 速度,- 分配)。

你会推荐什么?如何在没有中间字符串的情况下执行转换?是否有更快的方法来执行转换?

编辑:

我正在处理的字节数组总是包含 ASCII 编码的数据。数字可以是负数。对于双值指数格式是允许的。不允许使用十六进制整数。

4

3 回答 3

3

如何在没有中间字符串的情况下执行转换?

好吧,您可以轻松地将每个转换bytechar. 例如 - 未经测试:

private static long ConvertAsciiBytesToInt32(byte[] bytes)
{
    long value = 0;
    foreach (byte b in bytes)
    {
        value *= 10L;
        char c = b; // Implicit conversion; effectively ISO-8859-1
        if (c < '0' || c > '9')
        {
            throw new ArgumentException("Bytes contains non-digit: " + c);
        }
        value += (c - '0');
    }
    return value;
}

请注意,这确实假设它是 ASCII(或兼容的) - 如果您的字节数组实际上是 UTF-16(例如),那么它肯定会做错事。

另请注意,这不执行任何类型的长度验证或溢出检查......并且它不处理负数。如果需要,您可以添加所有这些,但我们对您的要求知之甚少,无法知道是否值得增加复杂性。

于 2013-01-19T09:50:35.523 回答
1

我不确定是否有一种简单的方法可以做到这一点,请注意它不适用于其他编码,在我的计算机上进行的测试表明这仅快 3 倍(我认为不值得) .

代码+测试:

class MainClass
{
    public static void Main(string[] args)
    {
        string str = "12341234";
        byte[] buffer = Encoding.ASCII.GetBytes(str);

        Stopwatch sw = Stopwatch.StartNew();
        for(int i = 0; i <   1000000 ;i ++)
        {
            long val = BufferToLong.GetValue(buffer);
        }
        Console.WriteLine (sw.ElapsedMilliseconds);
        sw.Restart();
        for (int i = 0 ; i < 1000000 ; i++)
        {
            string valStr = Encoding.ASCII.GetString(buffer);
            long val = long.Parse(valStr);
        }
        Console.WriteLine (sw.ElapsedMilliseconds);
    }
}

static class BufferToLong
{

    public static long GetValue(Byte[] buffer) {

        long number = 0;

        foreach (byte currentByte in buffer) {

            char currentChar = (char)currentByte;
            int currentDigit = currentChar - '0';

            number *= 10 ;
            number += currentDigit;

        }

        return number;
    }

}
于 2013-01-19T09:49:39.767 回答
0

最后,我创建了 C# 版本的strol函数。这个函数是 CRT 自带的,CRT 的源代码是 Visual Studio 自带的。

结果方法与@Jon Skeet 在他的回答中提供的代码几乎相同,但还包含一些溢出检查。

在我的例子中,所有的改变在速度和内存方面都被证明是非常有用的。

于 2013-02-17T16:33:55.867 回答