c# - 在 .NET 中避免双重转换(字节 [ ] 到字符串到单个)的方法?

标签 c# .net vb.net string

在低延迟 HFT 应用程序中,我有套接字接收包含股市数据的 Byte[] 消息。

在供应商协议(protocol)中,股票价格字段是包含 ASCII 字符序列的 Byte[]
IE。字节序列[51-51-46-56]对应ascii字符[3-3-.-8],等于33.8数。

实际上在消息解析过程中,我将 Byte[] 转换为字符串,然后将字符串转换为 Single/float。

有没有办法避免这种双重转换,直接将 Byte[] 转换为 single/float ?
其次,有没有一种方法可以避免使用在 NET 中效率低下(不可变垃圾收集倾向)的字符串类型?

提前致谢。

问候

[编辑 2019 年 1 月]:这是 3 年来完美运行的最终解决方案:

/// <summary> Read a Double precision float field in GL format from the stream and advances stream position of n (1 of field lenght flag + field lenght). </summary>
/// <returns>-1 in case of error, Double precision floating point value ROUNDED TO 8 DECIMAL PLACES in case of success </returns>
/// <param name="IniPos"> Initial Stream Position</param>
public double ReadGLFieldAsDouble(long IniPos = -1)
{
// --
if (IniPos >= 0)
    Strm.Position = IniPos;
int FLenght = Strm.ReadByte - 32; // case of "01000" SW Snapshot, field 7 doesn't exists, but in the message is a blank (32)
                                  // --early exit
if (FLenght <= 0)
    return -1; // a blank field (byte 32) returns -1
if (Strm.Length - Strm.Position < FLenght)
    return -1;
// --
double Dbl = 0;
int Cpos = -1;
int b = 0;
int sign = 1;

// --Builds as Integer with no point Separator
for (int i = 0; i < FLenght ; i++)
{
    b = Strm.ReadByte;
    switch (b)
    {
        case 45: // ASCII 45="-" sign
            {
                sign = -1;
                break;
            }

        case 46: // ASCII 46 is decimal point="." ; ASCII 44 is comma=","
            {
                Cpos = i; // decimal point position
                break;
            }

        default:
            {
                Dbl = Dbl * 10 + (b - 48); // increments as integer ASCII 48=0
                break;
            }
    }
}

// --Transforms in floating point  dividing by power of 10, multiplies by sign and returns
if (Cpos != -1)
    Dbl = (Dbl / (Math.Pow(10, (FLenght - 1 - Cpos))));
return Math.Round(sign * Dbl, 8);
}

最佳答案

 byte[] arr = new byte[] { 51, 51, 46, 56};
 double res = 0, floatindex = 0.1;
 bool isFraction = false;
 for (int i = 0; i < arr.Length; i++)
 {
    if (arr[i] == 46)
    {
        isFraction = true;
        continue;
    }

    if (!isFraction)
        res = 10*res + arr[i] - 48;
    else
    {
        res += (arr[i] - 48)*floatindex;
        floatindex /= 10.0;
    }
}
return res;

从文化的角度来看,它假定您始终有一个“点”来标记小数点分隔符(而不是像法国文化中那样的逗号)

关于c# - 在 .NET 中避免双重转换(字节 [ ] 到字符串到单个)的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32606412/

相关文章:

c# - 如何通过场景名称获取场景中的游戏对象列表,但只能获取一次?

.net - 使用第 7 层或第 4 层进行负载平衡

c# - 将 Null 附加到 `StringBuilder`

vb.net - 从 vb.net 打印时 Excel 中的换行符

javascript - 复选框总是返回 false

c# - 如何在Windows 7下 "Install"/"Enable".Net 3.5 SP1?

c# - Mutex.waitOne 在特定机器上总是返回 False

C# 构建一个字符串,评估另一个字符串作为模板/规则/格式来执行它

c# - 保留插入顺序的通用键/值对集合?

vb.net - 代码片段快捷方式 VB.NET