2014-11-05 3 views
4

По вопросу, «Can I convert long to int?», лучший способ в C# преобразовать длинный к ИНТ:Как я могу безопасно уменьшить длину до int?

int myIntValue = unchecked((int)myLongValue); 

Как я могу это сделать в VB.NET? У VB.NET нет понятия неконтролируемого моего понимания.

Когда я конвертирую код в конвертер, он говорит, что использует CInt(). Но CInt выбрасывает system.overflowexception. Использование unchecked в C# предотвращает исключение system.overflow.

Я предпочел бы не исключение.

Dim x As Long = Int32.MaxValue 
x = x + 100 
Console.WriteLine(x) 

Dim y As Integer = CInt(x) 
Console.WriteLine(y) 
+4

Какое значение вы хотите использовать VB.NET для длинного значения, большего, чем 'Int.MaxValue'? –

+0

VB.NET делает, но вы должны собрать всю свою сборку таким образом. Наверное, не умная идея. –

+1

@Cory: Это по умолчанию на C# - многие люди, похоже, в порядке с ним. Лично мне понравилась проверенная арифметика в большинстве случаев ... –

ответ

7

Как вы можете видеть в ответы на мои related, similar question, есть w ays, чтобы сделать такие вещи, но ничего более удобного, чем простой блок Try/Catch. Если вы хотите, чтобы избежать неэффективности Try/Catch блока, я рекомендовал бы проверить значение первой, как это:

If (myLongValue >= Integer.MinValue) AndAlso (myLongValue <= Integer.MaxValue) Then 
    myIntValue = CInt(myLongValue) 
End If 

Или, если вы хотите, чтобы установить значение на что-то конкретное, когда он находится за пределами диапазон:

If myLongValue < Integer.MinValue Then 
    myIntValue = Integer.MinValue 
ElseIf myLongValue > Integer.MaxValue Then 
    myIntValue = Integer.MaxValue 
Else 
    myIntValue = CInt(myLongValue) 
End If 

Если вы хотите сделать его более удобным, вы можете сделать его функцией. Если удобство является конечной целью, вы можете даже сделать его метод расширения:

<Extension> 
Public Function AsInt32(value As Long) As Integer 
    If value < Integer.MinValue Then 
     Return Integer.MinValue 
    ElseIf value > Integer.MaxValue Then 
     Return Integer.MaxValue 
    Else 
     Return CInt(value) 
    End If 
End Function 
+0

И если 'myLongValue' находится за пределами этого диапазона? –

+0

Просто добавьте и 'Else' и сделайте все, что хотите. –

+1

Вы можете закоротить свой оператор 'If', используя' AndAlso'. –

1

Есть ли функция преобразования уже написано, что будет проверять, если его больше, чем это, и если нет, то установите его в Int32.MaxValue?

Нет, но это было бы просто:

Dim l as Long = Int32.MaxValue + 12433243243 

Dim i as Int32 
if l > int32.MaxValue Then 
    i = int32.MaxValue 
elseIf l < int32.MinValue 
    i = int32.MinValue 
Else 
    i = CInt(l) 
End If 

Или в одной строке:

i = if(l > int32.MaxValue, int32.MaxValue, if(l < int32.MinValue, int32.MinValue, CInt(l))) 

Или с помощью Math.Min:

i = CInt(Math.Max(Math.Min(l, int32.MaxValue), int32.MinValue)) 
+1

Было бы хорошо обрабатывать числа xpda

+0

Версия Math.Min чиста и работает над образцом OPs. – perry

+0

@xpda Согласен. Исправлена. –

0

Вы можете использовать функцию мод с Convert.ToInt32:

i = Convert.ToInt32(x Mod (Int32.MaxValue)) 
+0

Закрыть, но это возвращает 100 (только остаток). – perry

+0

Вы можете использовать это вместе с одним из других ответов, чтобы разделить Long на два Ints, так что это по-прежнему полезно. – perry

0

внеофисный способ выполнения такого рода операции будет:

Function UInt64ToInt32Wrap(v As UInt64) As Int32 
    Return CInt((CUInt(v And &HFFFFFFFFUI) Xor &H80000000UI) + &H80000000) 
End Function 
Function Int64ToInt32Wrap(v As Int64) As Int32 
    Return CInt(((v And &HFFFFFFFFL) Xor &H80000000L) + &H80000000) 
End Function 
Function UInt32ToInt32Wrap(v As UInt32) As Int32 
    Return CInt((v Xor &H80000000UI) + &H80000000) 
End Function 

Обратите внимание, что в каждом случае последнее шестнадцатеричное значение является Int32 со значением -2147483648, поэтому добавлять его в беззнаковый тип приведет к продвижению в Int64; добавив, что к результату предыдущего XOR всегда будет выводиться значение, которое находится в диапазоне для Int32.

Желательно, чтобы что-то вроде того, что было предусмотрено в качестве встроенного компилятора, поскольку операции не имеют разветвления, и JIT, вероятно, может свести все к 32-разрядной «xor» и 32-разрядной команде «добавить» , для этого не нужно использовать код ANY.

Кстати, я думаю, что другой подход состоял бы в определении структуры с атрибутом «LayoutKind.Explicit», который перекрывал бы Int32 и UInt32; что, вероятно, устранит ненужные взаимно-аннулирующие арифметические операции, но это может заставить джиттер хранить значение в памяти и перезагружать его, когда он мог иначе хранить вещи в регистрах.

1

Вот довольно безболезненный способ спускать длинный путь к int, просто извлекая 32-разрядные разряды младшего разряда без выброса исключения. Нет 64-битного деления, никаких блоков try/catch, просто бит-скручивание и одно сравнение.

Private Function CastLongToInt(x As Long) As Integer 
    Dim value As Integer = CType(x And &H7FFFFFFFL, Integer) ' get the low order 31 bits 

    ' If bit 32 (the sign bit for a 32-bit signed integer is set, we OR it in 
    If (0 <> (x And &H80000000L)) Then 
     value = value Or &H80000000I 
    End If 

    Return value 
End Function 

Вот когда проще цветопередача — только бит вертел. Нет никаких сравнений. Мы просто захватить 2 16-разрядные тетрады и собрать их в конечное значение:

Private Function CastLongToInt(x As Long) As Integer 
    Dim hiNibble As Integer = &HFFFFL And (x >> 16) 
    Dim loNibble As Integer = &HFFFFL And x 
    Dim value As Integer = (hiNibble << 16) Or loNibble 
    Return value 
End Function 

отредактирован Примечание:

Другим вариантом было бы использовать обнуляемого целое (System.Nullable<int>). В VB.Net, было бы что-то вроде этого:

Private Function TryCastLongToInt(x As Long) As Integer? 
    Dim value As Integer? 
    Try 
     value = CType(x, Integer) 
    Catch 
     ' This exception intentionall swallowed here 
    End Try 
    Return value 
End Function 

Или, если понятие намеренно отлова и глотания исключений ошибки вы:

Private Function TryCastLongToInt(x As Long) As Integer? 
    If (x < Integer.MinValue) Then Return Nothing 
    If (x > Integer.MaxValue) Then Return Nothing 
    Return x 
End Function 

В любом случае, возвращаемое значение будет либо целочисленное значение или Nothing, если 64-битное значение было вне домена 32-разрядного целого.

+0

Мой результат для обоих был -2147483549. Установите x в Long.MaxValue, и результат равен -1 ... – perry

+0

Это потому, что это дает вам эквивалент вашего примера C# в исходном вопросе. Код, подобный этому в C# 'long x = Long.MaxValue; int y = (int) x; 'просто дает вам 32 бита младшего разряда 64-битной длины. Поскольку 'Long.MaxValue'' 0x7FFFFFFFFFFFFFFF', ваш результат равен '0xFFFFFFFF'. Как подписанное 32-битное целое число, это представление -1. –

+0

Спасибо за объяснение. Неясно, чего хочет OP. «Есть ли уже написанная функция преобразования, которая будет проверять, если ее больше, а если нет, установите ее в Int32.maxvalue?» или это «Как я могу безопасно уменьшить длину до int?» ... во всяком случае, я думаю, что у него достаточно ответов, чтобы определить, какой из них подходит этой проблеме и нести вперед :) – perry

0

Большие ответы до сих пор, вот еще один похож на Стивена Doggart-х:

Dim x As Long = Int32.MaxValue 
x = x + 100 
Console.WriteLine(x) 

Dim y As Integer 
If x > Int32.MaxValue Then y = Int32.MaxValue Else y = x 
Console.WriteLine(y) 

Результаты:

2147483747 
2147483647 

Или:

Dim x As Long = Long.MaxValue 
Console.WriteLine(x) 

Dim y As Integer 
If x > Int32.MaxValue Then y = Int32.MaxValue Else y = x 
Console.WriteLine(y) 

Результаты:

9223372036854775807 
2147483647 

Заверните его в функции:

Function DownsizeLongToInt(ByVal x As Long) As Integer 
    Dim y As Integer 
    If x > Int32.MaxValue Then y = Int32.MaxValue Else y = x 
    Return y 
End Function 

Примечание имя функции. Я назвал это таким образом, чтобы указать, что это приведет к усечению/потере данных и не должно использоваться для «преобразования» Long в Int, которое может быть потерянным, а также может быть причиной того, почему различные конвертеры функции не пытаются это сделать. Просто догадка.

Смежные вопросы