Что самый быстрый путь состоит в том, чтобы преобразовать плавание [] к байту []?

Предполагая:

  • ваша первая таблица находится в A: B
  • ваша вторая таблица находится в D: E

Вы можете использовать это на B2 и перетащить:

=IFERROR(INDEX(E:E,MATCH(A2,D:D,0)),"")
12
задан Nick 7 March 2009 в 00:14
поделиться

8 ответов

Если бы Вы не хотите, чтобы какое-либо преобразование произошло, я предложил бы Буфер. BlockCopy ().

public static void BlockCopy(
    Array src,
    int srcOffset,
    Array dst,
    int dstOffset,
    int count
)

Например:

float[] floatArray = new float[1000];
byte[] byteArray = new byte[floatArray.Length * 4];

Buffer.BlockCopy(floatArray, 0, byteArray, 0, byteArray.Length);
7
ответ дан 2 December 2019 в 02:59
поделиться

Существует грязное быстрое (весьма безопасный код) способ сделать это:

[StructLayout(LayoutKind.Explicit)]
struct BytetoDoubleConverter
{
    [FieldOffset(0)]
    public Byte[] Bytes;

    [FieldOffset(0)]
    public Double[] Doubles;
}
//...
static Double Sum(byte[] data)
{
    BytetoDoubleConverter convert = new BytetoDoubleConverter { Bytes = data };
    Double result = 0;
    for (int i = 0; i < convert.Doubles.Length / sizeof(Double); i++)
    {
        result += convert.Doubles[i];
    }
    return result;
}

Это будет работать, но я не уверен в поддержке на Моно или более новых версиях CLR. Единственная странная вещь состоит в том что array.Length длина байтов. Это может быть объяснено, потому что это смотрит на длину массива, снабженную массивом, и потому что этот массив был массивом байтов, что длина все еще будет в длине байта. Индексатор действительно думает о Двойном существе восемь байтов шириной, таким образом, никакое вычисление не необходимо там.

Я искал его еще немного, и это на самом деле описано на MSDN, Как к: Создайте Объединение C/C++ при помощи Атрибутов (C# и Visual Basic), таким образом, возможности, это будет поддерживаться в будущих версиях. Я не уверен в Моно все же.

20
ответ дан 2 December 2019 в 02:59
поделиться

Преждевременная оптимизация является корнем всего зла! предложение @Vlad для итерации по каждому плаванию является намного более разумным ответом, чем переключение на байт []. Возьмите следующую таблицу времени выполнения для растущих чисел элементов (среднее число 50 выполнений):

Elements      BinaryWriter(float)      BinaryWriter(byte[])
-----------------------------------------------------------
10               8.72ms                    8.76ms
100              8.94ms                    8.82ms
1000            10.32ms                    9.06ms
10000           32.56ms                   10.34ms
100000         213.28ms                  739.90ms
1000000       1955.92ms                10668.56ms

Существует мало различия между двумя для небольших чисел элементов. После того как Вы входите в огромный диапазон числа элементов, время потратило копирование с плавания [] к байту [], явно перевешивает преимущества.

Поэтому пойдите с тем, что просто:

float[] data = new float[...];
foreach(float value in data)
{
    writer.Write(value);
}
18
ответ дан 2 December 2019 в 02:59
поделиться

Вы - богатое разрешение BinaryWriter сделать это для Вас. Там будет повторением по Вашему всему набору данных, независимо от которых метода Вы используете, таким образом, нет никакого смысла в проигрывании с байтами.

3
ответ дан 2 December 2019 в 02:59
поделиться

У нас есть класс под названием LudicrousSpeedSerialization, и он содержит следующий небезопасный метод:

    static public byte[] ConvertFloatsToBytes(float[] data)
    {
        int n = data.Length;
        byte[] ret = new byte[n * sizeof(float)];
        if (n == 0) return ret;

        unsafe
        {
            fixed (byte* pByteArray = &ret[0])
            {
                float* pFloatArray = (float*)pByteArray;
                for (int i = 0; i < n; i++)
                {
                    pFloatArray[i] = data[i];
                }
            }
        }

        return ret;
    }
0
ответ дан 2 December 2019 в 02:59
поделиться

Хотя можно получить a byte* использование указателя unsafe и fixed, Вы не можете преобразовать byte* кому: byte[] для устройства записи для принятия его в качестве параметра, не выполняя копию данных. Который Вы не хотите делать, поскольку это удвоит Ваш объем потребляемой памяти и добавит дополнительное повторение по неизбежному повторению, которое должно быть выполнено для вывода данных к диску.

Вместо этого Вы - все еще более обеспеченная итерация по массиву плаваний и записи каждого float устройству записи индивидуально, с помощью Write(double) метод. Это все еще будет быстро из-за буферизации в устройстве записи. Посмотрите sixlettervariablesчисла.

1
ответ дан 2 December 2019 в 02:59
поделиться

Хотя это в основном делает для цикла негласно, это действительно делает задание в одной строке

byte[] byteArray = floatArray.Select(
                    f=>System.BitConverter.GetBytes(f)).Aggregate(
                    (bytes, f) => {List<byte> temp = bytes.ToList(); temp.AddRange(f); return temp.ToArray(); });
-2
ответ дан 2 December 2019 в 02:59
поделиться

Есть способ избежать копирования памяти и повторения.

Вы можете использовать очень уродливый хак, чтобы временно изменить ваш массив на другой тип, используя (небезопасные) манипуляции с памятью.

Я тестировал этот хак как в 32-битной, так и в 64-битной ОС, поэтому он должен быть переносимым.

Исходный код + пример использования хранится по адресу https://gist.github.com/1050703 , но для вашего удобства я также вставлю его сюда:

public static unsafe class FastArraySerializer
{
    [StructLayout(LayoutKind.Explicit)]
    private struct Union
    {
        [FieldOffset(0)] public byte[] bytes;
        [FieldOffset(0)] public float[] floats;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct ArrayHeader
    {
        public UIntPtr type;
        public UIntPtr length;
    }

    private static readonly UIntPtr BYTE_ARRAY_TYPE;
    private static readonly UIntPtr FLOAT_ARRAY_TYPE;

    static FastArraySerializer()
    {
        fixed (void* pBytes = new byte[1])
        fixed (void* pFloats = new float[1])
        {
            BYTE_ARRAY_TYPE = getHeader(pBytes)->type;
            FLOAT_ARRAY_TYPE = getHeader(pFloats)->type;
        }
    }

    public static void AsByteArray(this float[] floats, Action<byte[]> action)
    {
        if (floats.handleNullOrEmptyArray(action)) 
            return;

        var union = new Union {floats = floats};
        union.floats.toByteArray();
        try
        {
            action(union.bytes);
        }
        finally
        {
            union.bytes.toFloatArray();
        }
    }

    public static void AsFloatArray(this byte[] bytes, Action<float[]> action)
    {
        if (bytes.handleNullOrEmptyArray(action)) 
            return;

        var union = new Union {bytes = bytes};
        union.bytes.toFloatArray();
        try
        {
            action(union.floats);
        }
        finally
        {
            union.floats.toByteArray();
        }
    }

    public static bool handleNullOrEmptyArray<TSrc,TDst>(this TSrc[] array, Action<TDst[]> action)
    {
        if (array == null)
        {
            action(null);
            return true;
        }

        if (array.Length == 0)
        {
            action(new TDst[0]);
            return true;
        }

        return false;
    }

    private static ArrayHeader* getHeader(void* pBytes)
    {
        return (ArrayHeader*)pBytes - 1;
    }

    private static void toFloatArray(this byte[] bytes)
    {
        fixed (void* pArray = bytes)
        {
            var pHeader = getHeader(pArray);

            pHeader->type = FLOAT_ARRAY_TYPE;
            pHeader->length = (UIntPtr)(bytes.Length / sizeof(float));
        }
    }

    private static void toByteArray(this float[] floats)
    {
        fixed(void* pArray = floats)
        {
            var pHeader = getHeader(pArray);

            pHeader->type = BYTE_ARRAY_TYPE;
            pHeader->length = (UIntPtr)(floats.Length * sizeof(float));
        }
    }
}

Использование таково:

var floats = new float[] {0, 1, 0, 1};
floats.AsByteArray(bytes =>
{
    foreach (var b in bytes)
    {
        Console.WriteLine(b);
    }
});
12
ответ дан 2 December 2019 в 02:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: