Существует ли хороший способ разделить интервал на два коротких замыкания (.NET)?

В прошлый раз, когда я проверил, следующее были пустые/пустые элементы, перечисленные в HTML5.

Допустимый для авторов: область, основа, br, седло, команда, встраивает, eventsource, час, img, ввела, связывается, meta, параметрический усилитель, источник

Недопустимый для авторов: basefont, bgsound, кадр, распорная деталь, wbr

Помимо некоторых, которые являются новыми в HTML5, который должен дать Вам общее представление о, которые могли бы поддерживаться при обслуживании XHTML в качестве текста/HTML. (Просто протестируйте их путем исследования произведенного DOM.)

Что касается XHTML служил application/xhtml+xml (который делает его XML), правила XML применяются, и любой элемент может быть пустым (даже при том, что DTD XHTML не может выразить этого).

27
задан jason 9 December 2009 в 18:55
поделиться

10 ответов

Это должно работать:

int original = ...;
byte[] bytes = BitConverter.GetBytes(original);
short firstHalf = BitConverter.ToInt16(bytes, 0);
short secondHalf = BitConverter.ToInt16(bytes, 2);

РЕДАКТИРОВАТЬ:

протестировано с 0x7FFFFFFF, оно работает

byte[] recbytes = new byte[4];
recbytes[0] = BitConverter.GetBytes(firstHalf)[0];
recbytes[1] = BitConverter.GetBytes(firstHalf)[1];
recbytes[2] = BitConverter.GetBytes(secondHalf)[0];
recbytes[3] = BitConverter.GetBytes(secondHalf)[1];
int reconstituted = BitConverter.ToInt32(recbytes, 0);
13
ответ дан 28 November 2019 в 04:34
поделиться

Это, безусловно, можно сделать без потери информации. В обоих случаях вы получаете 32 бита информации. Независимо от того, используются они для знаковых битов или нет, не имеет значения:

int original = ...;

short firstHalf = (short) (original >> 16);
short secondHalf = (short) (original & 0xffff);

int reconstituted = (firstHalf << 16) | (secondHalf & 0xffff);

Здесь восстановленный всегда будет равен исходному , следовательно, информация не будет потеряна.

Теперь значение знаков двух коротких замыканий - другое дело - firstHalf будет отрицательным, если и только если исходный отрицателен, но secondHalf будет отрицательным, если бит 15 (считая 0-31) из оригинала установлено, что не имеет особого смысла в исходной форме.

36
ответ дан 28 November 2019 в 04:34
поделиться

Ответ Джона , переведенный на Visual Basic и без переполнения:

Module Module1
    Function MakeSigned(ByVal x As UInt16) As Int16
        Dim juniorBits As Int16 = CType(x And &H7FFF, Int16)
        If x > Int16.MaxValue Then
            Return juniorBits + Int16.MinValue
        End If
        Return juniorBits
    End Function

    Sub Main()
        Dim original As Int32 = &H7FFFFFFF    
        Dim firstHalfUnsigned As UInt16 = CType(original >> 16, UInt16)
        Dim secondHalfUnsigned As UInt16 = CType(original And &HFFFF, UInt16)
        Dim firstHalfSigned As Int16 = MakeSigned(firstHalfUnsigned)
        Dim secondHalfSigned As Int16 = MakeSigned(secondHalfUnsigned)

        Console.WriteLine(firstHalfUnsigned)
        Console.WriteLine(secondHalfUnsigned)
        Console.WriteLine(firstHalfSigned)
        Console.WriteLine(secondHalfSigned)
    End Sub
End Module

Результаты:

32767
65535
32767
-1

В .NET CType (& Hffff, Int16) вызывает переполнение , а (короткий) 0xffff дает -1 (без переполнения). Это связано с тем, что по умолчанию компилятор C # использует непроверенные операции, а VB.NET проверяется.

Лично мне нравится ответ Агга , потому что мой код более сложен, а код Джона вызовет исключение переполнения в проверено .

Я также создал еще один ответ , основанный на коде класса BitConverter , оптимизированном для этой конкретной задачи. Однако он использует небезопасный код.

7
ответ дан 28 November 2019 в 04:34
поделиться

Если вы используете c ++, вас также могут заинтересовать StructLayout или объединения.

0
ответ дан 28 November 2019 в 04:34
поделиться

Из-за хранилища width (32 и 16 бит), преобразование Int32 в Int16 может означать потерю информации, если ваш Int32 больше 32767.

0
ответ дан 28 November 2019 в 04:34
поделиться

Почему нет? Давайте уменьшим количество битов для простоты: допустим, у нас есть 8 бит, из которых левый бит - минусовый бит.

[1001 0110] // representing -22

Вы можете сохранить его в 2 раза по 4 бита

[1001] [0110] // representing   -1 and 6

Я не понимаю, почему это было бы невозможно, у вас дважды есть 8-битная информация

РЕДАКТИРОВАТЬ: Для простоты я не просто уменьшил биты, но и не использую метод 2-дополнительных. В моих примерах левый бит обозначает минус,

3
ответ дан 28 November 2019 в 04:34
поделиться

Если вы посмотрите на битовое представление, то вы правы.

Вы можете сделать это с целыми числами без знака, поскольку они не имеют знакового бита.

0
ответ дан 28 November 2019 в 04:34
поделиться

да, это можно сделать, используя маскирование и битовые сдвиги

 Int16 a,b;
 Int32 c;

 a = (Int16) (c&0xffff);
 b = (Int16) ((c>>16)&0xffff);

EDIT

, чтобы ответить на комментарий. Реконструкция работает нормально:

 Int16 a, b;
 Int32 c = -1;

 a = (Int16)(c & 0xffff);
 b = (Int16)((c >> 16) & 0xffff);

 Int32 reconst = (((Int32)a)&0xffff) | ((Int32)b << 16);

 Console.WriteLine("reconst = " + reconst);

Протестировано, как и ожидалось, выдает -1.

РЕДАКТИРОВАТЬ2: изменена реконструкция. Повышение Int16 до Int32 привело к расширению всех битов знака. Забыл об этом, его нужно было связать И.

4
ответ дан 28 November 2019 в 04:34
поделиться

Вы можете использовать StructLayout в VB.NET:

исправление: слово - 16 бит, двойное слово - 32 бит

<StructLayout(LayoutKind.Explicit, Size:=4)> _
   Public Structure UDWord
      <FieldOffset(0)> Public Value As UInt32
      <FieldOffset(0)> Public High As UInt16
      <FieldOffset(2)> Public Low As UInt16

      Public Sub New(ByVal value As UInt32)
         Me.Value = value
      End Sub

      Public Sub New(ByVal high as UInt16, ByVal low as UInt16)
         Me.High = high
         Me.Low = low
      End Sub
   End Structure

Подпись будет такой же, только вместо этого используются эти типы

<StructLayout(LayoutKind.Explicit, Size:=4)> _
   Public Structure DWord
      <FieldOffset(0)> Public Value As Int32
      <FieldOffset(0)> Public High As Int16
      <FieldOffset(2)> Public Low As Int16

      Public Sub New(ByVal value As Int32)
         Me.Value = value
      End Sub

      Public Sub New(ByVal high as Int16, ByVal low as Int16)
         Me.High = high
         Me.Low = low
      End Sub
   End Structure

РЕДАКТИРОВАТЬ:

Я как бы торопился несколько раз публиковал / редактировал свой ответ, но еще не объяснил это решение, так что я чувствую, что не завершил свой ответ. Итак, я собираюсь сделать это сейчас:

Использование StructLayout в явном виде в структуре требует, чтобы вы указали расположение каждого поля (по смещению в байтах) [StructLayoutAttribute] с атрибутом FieldOffset [FieldOffsetAttribute]

С помощью этих двух атрибутов вы можете создавать перекрывающиеся поля, также известные как объединения .

Первое поле (DWord.Value) будет 32-битным целым числом со смещением 0 (нуль). Чтобы разделить это 32-битное целое число, у вас должно быть два дополнительных поля, начинающихся снова со смещения 0 (ноль), а затем второе поле на 2 байта дальше, потому что 16-битное (короткое) целое число равно 2 байтам.

Из того, что я напомним, обычно, когда вы разделяете целое число, они обычно называют первую половину «высокой», а вторую половину - «низкой»; таким образом назвав два моих других поля.

Используя такую ​​структуру, вы могли бы затем создать перегрузки для операторов и сужение / сужение типов, чтобы легко переходить от типа Int32 к этой структуре DWord, а также к сравнениям Оператор Перегрузка в VB.NET

2
ответ дан 28 November 2019 в 04:34
поделиться

Небезопасный код в C #, переполнение не происходит, автоматическое определение порядка байтов:

using System;
class Program
{
    static void Main(String[] args)
    {
        checked // Yes, it works without overflow!
        {
            Int32 original = Int32.MaxValue;
            Int16[] result = GetShorts(original);
            Console.WriteLine("Original int: {0:x}", original);
            Console.WriteLine("Senior Int16: {0:x}", result[1]);
            Console.WriteLine("Junior Int16: {0:x}", result[0]);
            Console.ReadKey();
        }
    }
    static unsafe Int16[] GetShorts(Int32 value)
    {
        byte[] buffer = new byte[4];
        fixed (byte* numRef = buffer)
        {
            *((Int32*)numRef) = value;
            if (BitConverter.IsLittleEndian)
                return new Int16[] { *((Int16*)numRef), *((Int16*)numRef + 1) };
            return new Int16[] { 
                (Int16)((numRef[0] << 8) | numRef[1]),  
                (Int16)((numRef[2] << 8) | numRef[3])
            };
        }
    }
}
2
ответ дан 28 November 2019 в 04:34
поделиться