2014-12-27 3 views
2

Даже если это звучит просто, C# делает это тяжелая работа, чтобы добавить целое число (смещение) в беззнаковое значение:Добавить подписанное целое число без знака в C#

unsigned uintValue; 
int offset; 
// ... 
uintValue += offset; // causes error CS0266 

Это может быть сделано путем преобразования смещение к значению, но это выглядит несколько небезопасным и неудобным для меня, и это рискованно, если смещение имеет меньший тип, чем uintValue. Есть ли элегантное решение для этой простой проблемы, не используя тонны уродливого преобразования типов?

В моей заявке offset может быть положительным или отрицательным числом, в противном случае решение было бы тривиальным.

+2

«Это может быть сделано путем преобразования смещения в знаковое значение» Это уже есть. – Boann

+0

Нет, и преобразования типов не являются взломанными, просто используйте с uintValue на основе значения смещения. –

ответ

0

Приведение необходимо здесь. Рассмотривать следующее:

uIntValue = (offset < 0 ? 
       uIntValue - (uint)(offset * (-1)) : 
       uIntValue + (uint)(offset)); 

Это означает, что если смещение имеет отрицательное значение, это сделает его положительным и уменьшить его от uIntValue, и если смещение положительно, это будет просто добавить его

1

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

  • Преобразовать оба операнда к long, чтобы гарантировать достаточное количество битов, выполнить операцию, и отбрасывать результат обратно unsigned или
  • Сделать условно на основе знака offset, и используйте + или - с абсолютным значением смещения, соответствующим образом отлитым до unsigned.

Первый подход проще в коду, но немного более расточителен, потому что он принимает дополнительный четыре байта:

uintValue = (unsigned)((long)uintValue + offset); 

Однако, она свободна от условных, так что это может быть быстрее, в конце концов, ,

Примечание: Само собой разумеется, что эта схема создает недопустимый результат, когда результат сложения отрицательный.

+0

В проверенном арифметическом контексте приведенное выше не будет выполнено, если значение без знака обернется. В зависимости от того, для чего он используется, это может быть хорошим или плохим. Слишком плохо, что побитовый оператор '&' не имеет перегрузок для 'UInt32 & UInt64 -> Uint32',' UInt32 и Int64 -> Uint32', 'UInt64 и UInt32 -> UInt32' и' Int64 & UInt32 -> Uint32 ', так как такие перегрузки избегали бы глупого приведения, когда бит-маскировка вычислительного результата. – supercat

0

Вы должны бросить операнд к тому же типу, компенсируя возможные отрицательные значения:

 uint uintValue = 1000; 
     int offset = -1000; 
     uintValue = (offset < 0 ? uintValue - (uint)(-1 * offset) : uintValue + (uint)offset); 
Смежные вопросы