¿Puedo convertir long a int?

Respuestas:

218

Solo hazlo (int)myLongValue. Hará exactamente lo que desee (descartar MSB y tomar LSB) en uncheckedcontexto (que es el valor predeterminado del compilador). Se lanzará OverflowExceptionen checkedcontexto si el valor no cabe en un int:

int myIntValue = unchecked((int)myLongValue);
Mehrdad Afshari
fuente
15
Para cualquier otra persona que tuviera la misma pregunta que yo hice: tenga en cuenta que descartar los MSB puede tener un efecto en el signo del resultado. Con lo anterior, myIntValuepuede terminar negativo cuando myLongValuees positivo ( 4294967294 => -2) y viceversa ( -4294967296 => 0). Por lo tanto, al implementar una CompareTooperación, por ejemplo, no puede emitir felizmente el resultado de restar uno longde otro a un inty devolverlo; para algunos valores, su comparación arrojaría un resultado incorrecto.
TJ Crowder
21
@ Chris: new Random()usos Environment.TickCountdebajo del capó; No es necesario sembrar manualmente con los tics del reloj.
Mehrdad Afshari
@MehrdadAfshari, ¿siempre ha sido así?
Chris Marisic
3
Aunque esto fue hace años, la razón por la que lo usé en el nuevo Random fue porque estaba obteniendo los mismos resultados exactos en una prueba unitaria y quería variación. Usar el número me dio varianza.
Chris Marisic
3
El contexto predeterminado es unchecked, entonces, a menos que lo haya cambiado explícitamente, entonces la uncheckedpalabra clave (como se muestra en esta respuesta y el comentario de @ ChrisMarisic, etc.) no es necesaria, y int myIntValue = (int)myLongValuees exactamente equivalente. Sin embargo, tenga en cuenta que independientemente de si usa la uncheckedpalabra clave o no, está obteniendo el comportamiento de truncamiento grosero no matemático descrito por @TJCrowder, donde el signo puede voltearse en algunos casos de desbordamiento. La única forma de garantizar realmente la corrección matemática es utilizar el checked(...)contexto, donde esos casos arrojarán una excepción.
Glenn Slayden
35
Convert.ToInt32(myValue);

Aunque no sé qué hará cuando sea mayor que int.MaxValue.

Max Schmeling
fuente
42
"Aunque no sé qué hará cuando sea mayor que int.MaxValue" Lanzará un OverflowException, que es exactamente lo que el OP no quiere: msdn.microsoft.com/en-us/library/d4haekc4.aspx
TJ Crowder
44
Pruebe si myValue> Integer.Max antes de ejecutar la conversión, si necesita realizar otro procesamiento cuando myValue> Integer.Max. Convert.ToInt32 (myValue) se desbordará (sin excepción, creo) de lo contrario. Este método también funciona en VB.NET.
TamusJRoyce
3
Si bien (int) es válido, Convert es una mejor respuesta. Es mejor tener excepciones raras que datos extraños.
Richard junio
1
@ RichardJune Um, ¿no? El OP aquí dice explícitamente : " Si el valor de long> int.MaxValue, me complace dejar que se ajuste " . Puedo ver argumentando su declaración en general, pero en este caso específico , no, Convertno es bueno.
ruffin
if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Sergey
15

A veces no estás realmente interesado en el valor real, sino en su uso como suma de comprobación / código hash . En este caso, el método incorporado GetHashCode()es una buena opción:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();
realbart
fuente
77
Ha pasado un tiempo desde que se dio esta respuesta, aunque quiero mencionar que la implementación del código hash puede diferir entre las versiones de .NET. En realidad, esto podría no estar sucediendo, pero no hay garantía de que este valor sea el mismo entre diferentes aplicaciones ejecutadas / dominios de aplicación.
Caramiriel
1
Para agregar a lo que dice @Caramiriel: si lo usa como un código hash temporal , durante su sesión de aplicación actual, entonces GetHashCodees una opción adecuada. Si busca una suma de comprobación persistente , un valor que será el mismo cuando ejecute su aplicación más tarde, no lo use GetHashCode, ya que no se garantiza que sea el mismo algoritmo para siempre.
ToolmakerSteve
9

La forma más segura y rápida es usar Bit Masking antes de lanzar ...

int MyInt = (int) ( MyLong & 0xFFFFFFFF )

El 0xFFFFFFFFvalor de Máscara de bits ( ) dependerá del tamaño de Int porque el tamaño Int depende de la máquina.

Mashake
fuente
Debe decidir qué desea que suceda cuando el resultado se desborde o se convierta en un número negativo. Lo que muestra todavía se desbordará, IIRC, porque está dejando que la señal se filtre. [Como se mencionó en otra respuesta, en uncheckedcontexto no obtendrá un desbordamiento, pero no necesita enmascararse uncheckedpara evitar el desbordamiento, por lo que solo se necesita una solución en checkedcontexto.] Ejemplo para 16 bits. Presas firmadas de 16 bits (-32768, 32767). El enmascaramiento con 0xFFFF permite valores de hasta 65535, lo que provoca un desbordamiento, IIRC. Podría enmascarar para evitar el bit de signo, 0x7FFF o 0x7FFFFFFF, si solo desea positivo.
ToolmakerSteve
1

Se puede convertir por

Método Convert.ToInt32

Pero arrojará una Excepción de desbordamiento si el valor está fuera del rango del Tipo Int32. Una prueba básica nos mostrará cómo funciona:

long[] numbers = { Int64.MinValue, -1, 0, 121, 340, Int64.MaxValue };
int result;
foreach (long number in numbers)
{
   try {
         result = Convert.ToInt32(number);
        Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
                    number.GetType().Name, number,
                    result.GetType().Name, result);
     }
     catch (OverflowException) {
      Console.WriteLine("The {0} value {1} is outside the range of the Int32 type.",
                    number.GetType().Name, number);
     }
}
// The example displays the following output:
//    The Int64 value -9223372036854775808 is outside the range of the Int32 type.
//    Converted the Int64 value -1 to the Int32 value -1.
//    Converted the Int64 value 0 to the Int32 value 0.
//    Converted the Int64 value 121 to the Int32 value 121.
//    Converted the Int64 value 340 to the Int32 value 340.
//    The Int64 value 9223372036854775807 is outside the range of the Int32 type.

Aquí hay una explicación más larga.

nzrytmn
fuente
0

No

(int) Math.Min(Int32.MaxValue, longValue)

ser la forma correcta, matemáticamente hablando?

Rémy Esmery
fuente
Esto sujetaría el longValuerepresentable más cercano intsi el valor original es demasiado grande. Pero carece del mismo tratamiento de entradas demasiado negativas, lo que en su lugar perdería los bits más significativos; Tendría que comparar con Int32.MinValuetambién. Sin embargo, el póster original no parecía querer sujetarlo.
Jeppe Stig Nielsen
En mi humilde opinión, a veces es mejor obtener una excepción que un valor incorrecto, que Int32.MaxValue sería ...
G. Goncharov
0

La siguiente solución se truncará en int.MinValue / int.MaxValue si el valor está fuera de los límites de Integer.

myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)
Clemente
fuente
0

Una forma posible es usar el operador de módulo para dejar que los valores permanezcan en el rango int32 y luego convertirlo en int.

var intValue= (int)(longValue % Int32.MaxValue);
Andre
fuente