Posso converter muito tempo para int?

142

Eu quero converter longpara int.

Se o valor de long> int.MaxValue, fico feliz em deixá-lo por aí.

Qual é a melhor maneira?

Apesar
fonte

Respostas:

218

Apenas faça (int)myLongValue. Ele fará exatamente o que você deseja (descartando MSBs e recebendo LSBs) no uncheckedcontexto (que é o padrão do compilador). Será lançada OverflowExceptionno checkedcontexto se o valor não couber em um int:

int myIntValue = unchecked((int)myLongValue);
Mehrdad Afshari
fonte
15
Para qualquer outra pessoa que tivesse a mesma pergunta que eu fiz: Observe que o descarte dos MSBs pode afetar o sinal do resultado. Com o exposto, myIntValuepode acabar negativo quando myLongValuepositivo ( 4294967294 => -2) e vice-versa ( -4294967296 => 0). Portanto, ao implementar uma CompareTooperação, por exemplo, você não pode converter felizmente o resultado de subtrair um longdo outro para um inte retornar esse valor; para alguns valores, sua comparação produziria um resultado incorreto.
TJ Crowder
21
@ Chris: new Random()usa Environment.TickCountsob o capô; não é necessário semear manualmente com marcações de relógio.
Mehrdad Afshari
@MehrdadAfshari esse sempre foi o caso?
Chris Marisic 9/10/11
3
Mesmo que isso tenha ocorrido anos atrás, a razão pela qual eu o usei no novo Random foi que eu estava obtendo os mesmos resultados exatos em um teste de unidade e queria variação. Usar o número me deu variação.
22615 Chris Marisic
3
O contexto padrão é unchecked, portanto, a menos que você o tenha alterado explicitamente, a uncheckedpalavra - chave (conforme mostrado nesta resposta e no comentário de @ ChrisMarisic etc.) não é necessária e int myIntValue = (int)myLongValueé exatamente equivalente. No entanto, observe que, independentemente de você usar uncheckedou não a palavra - chave, você está obtendo o comportamento de truncamento não-matemático descrito por @TJCrowder, em que o sinal pode virar em alguns casos de estouro. A única maneira de garantir verdadeiramente a correção matemática é usar o checked(...)contexto, onde esses casos gerarão uma exceção.
Glenn Slayden
35
Convert.ToInt32(myValue);

Embora eu não saiba o que fará quando for maior que int.MaxValue.

Max Schmeling
fonte
42
"Embora eu não saiba o que fará quando for maior que int.MaxValue" Ele lançará um OverflowException, exatamente o que o OP não deseja: msdn.microsoft.com/en-us/library/d4haekc4.aspx
TJ Crowder #
4
Teste se myValue> Integer.Max antes de executar a conversão, se você precisar fazer outro processamento quando myValue> Integer.Max. Convert.ToInt32 (myValue) irá estourar (sem exceção, acredito) caso contrário. Este método também funciona no VB.NET.
TamusJRoyce
3
Enquanto (int) for válido, o Convert é uma resposta melhor. Melhor ter exceções estranhas do que dados estranhos.
9116 June June
1
@RichardJune Hum, não? O OP aqui diz explicitamente : " Se o valor de long> int.MaxValue, fico feliz em deixá-lo por aí. " Posso ver discutindo sua afirmação em geral, mas nesse caso específico , não, Convertnão é bom.
Ruffin
if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Sergey
15

Às vezes, você não está realmente interessado no valor real, mas em seu uso como soma de verificação / código de hash . Nesse caso, o método interno GetHashCode()é uma boa opção:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();
realbart
fonte
7
Já faz um tempo desde que essa resposta foi dada, embora eu queira mencionar que a implementação do código de hash pode diferir entre as versões do .NET. Isso pode não estar realmente acontecendo, mas não há garantia de que esse valor seja o mesmo entre diferentes execuções de aplicativos / domínios de aplicativo.
Caramiriel
1
Para adicionar o que @Caramiriel está dizendo: se estiver usando como um código hash temporário , durante a sessão atual do aplicativo, GetHashCodeserá uma escolha apropriada. Se você estiver buscando uma soma de verificação persistente - um valor que será o mesmo quando você executar o aplicativo posteriormente, não use GetHashCode, pois não é garantido que ele seja o mesmo algoritmo para sempre.
Home
9

A maneira mais rápida e segura é usar o Bit Masking antes do lançamento ...

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

O 0xFFFFFFFFvalor da máscara de bits ( ) dependerá do tamanho de Int porque o tamanho de Int depende da máquina.

Mashake
fonte
Você precisa decidir o que deseja que aconteça quando o resultado exceder ou se tornar um número negativo. O que você mostra ainda transbordará, IIRC, porque você está deixando o sinal passar. [Como mencionado em outra resposta, no uncheckedcontexto você não receberá um estouro - mas não precisará mascarar-se uncheckedpara evitar o estouro; portanto, uma solução é necessária apenas no checkedcontexto.] Exemplo para 16 bits. Retenções assinadas de 16 bits (-32768, 32767). O mascaramento com 0xFFFF permite valores de até 65535, causando estouro, IIRC. Pode mascarar para evitar o bit de sinal, 0x7FFF ou 0x7FFFFFFF, se desejar apenas positivo.
Home
1

Pode converter por

Método Convert.ToInt32

Mas ele lançará uma OverflowException se o valor estiver fora do intervalo do Tipo Int32. Um teste básico nos mostrará como 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.

Aqui há uma explicação mais longa.

nzrytmn
fonte
0

Não

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

ser o caminho correto, matematicamente falando?

Rémy Esmery
fonte
Este seria prender o longValueao representável mais próximo intse o valor original é enorme. Mas falta o mesmo tratamento para entradas muito negativas, que perderiam os bits mais significativos; você precisaria comparar com Int32.MinValuetambém. O pôster original não parecia querer fixação, no entanto.
Jeppe Stig Nielsen
Às vezes, IMHO é melhor obter exceção do que valor errado, que Int32.MaxValue seria ...
G. Goncharov
0

A solução a seguir será truncada para int.MinValue / int.MaxValue se o valor estiver fora dos limites do número inteiro.

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

Uma maneira possível é usar o operador módulo para deixar apenas os valores permanecerem no intervalo int32 e depois convertê-lo para int.

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