Posso convertire long in int?


Risposte:


218

Fallo e basta (int)myLongValue. Farà esattamente quello che vuoi (scartando MSB e prendendo LSB) nel uncheckedcontesto (che è l'impostazione predefinita del compilatore). Sarà gettare OverflowExceptionnel checkedcontesto se il valore non rientra in una int:

int myIntValue = unchecked((int)myLongValue);

15
Per chiunque abbia avuto la stessa domanda che ho fatto: nota che scartare gli MSB può avere un effetto sul segno del risultato. Con quanto sopra, myIntValuepuò risultare negativo quando myLongValueè positivo ( 4294967294 => -2) e viceversa ( -4294967296 => 0). Quindi, quando si implementa CompareToun'operazione, per esempio, non si può felicemente lanciare il risultato sottraendo l'uno longdall'altro inte restituirlo; per alcuni valori, il confronto produrrebbe un risultato errato.
TJ Crowder,

21
@Chris: new Random()utilizza Environment.TickCountsotto il cofano; non è necessario eseguire il seeding manuale con i segni di spunta dell'orologio.
Mehrdad Afshari,

@MehrdadAfshari è sempre stato così?
Chris Marisic,

3
Anche se questo è stato anni fa, la ragione per cui l'ho usato nel nuovo Random era che stavo ottenendo gli stessi esatti risultati in un test unitario e volevo varianza. L'uso del numero mi ha dato una varianza.
Chris Marisic,

3
Il contesto predefinito è unchecked, quindi a meno che tu non l'abbia modificato esplicitamente, la uncheckedparola chiave (come mostrato in questa risposta e nel commento di @ ChrisMarisic, ecc.) Non è necessaria ed int myIntValue = (int)myLongValueè esattamente equivalente. Tuttavia, tieni presente che, indipendentemente dal fatto che tu usi uncheckedo meno la parola chiave, stai ottenendo il comportamento di troncamento non matematico descritto da @TJCrowder in cui il segno può capovolgere in alcuni casi di overflow. L'unico modo per garantire veramente la correttezza matematica è utilizzare il checked(...)contesto, in cui tali casi genereranno un'eccezione.
Glenn Slayden,

35
Convert.ToInt32(myValue);

Anche se non so cosa farà quando è maggiore di int.MaxValue.


42
"Anche se non so che cosa farà quando è maggiore di int.MaxValue" Lancerà un OverflowException, che è esattamente ciò che l'OP non vuole: msdn.microsoft.com/en-us/library/d4haekc4.aspx
TJ Crowder,

4
Verifica se myValue> Integer.Max prima di eseguire la conversione, se devi eseguire altre elaborazioni quando myValue> Integer.Max. Convert.ToInt32 (myValue) traboccerà (senza eccezione, credo) altrimenti. Questo metodo funziona anche in VB.NET.
TamusJRoyce,

3
Mentre (int) è valido, Convert è una risposta migliore. Meglio avere strane eccezioni rispetto a dati strani.
Richard,

1
@RichardJune Um, no? L'OP qui dice esplicitamente : " Se il valore di long> int.MaxValue, sono felice di lasciarlo avvolgere. " Posso vedere argomentare la tua affermazione in generale, ma in questo caso specifico , no, Convertnon va bene.
ruffin,

if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Sergey,

15

A volte non sei effettivamente interessato al valore reale, ma al suo utilizzo come checksum / hashcode . In questo caso, il metodo integrato GetHashCode()è una buona scelta:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();

7
È passato un po 'di tempo da quando è stata data questa risposta, anche se voglio menzionare che l'implementazione dell'hashcode potrebbe differire tra le versioni di .NET. In realtà ciò potrebbe non accadere, ma non esiste alcuna garanzia che questo valore sia lo stesso tra diverse esecuzioni / appdomain di applicazioni.
Caramiriel,

1
Per aggiungere a ciò che @Caramiriel sta dicendo: se si utilizza come hashcode temporaneo , durante la sessione dell'app corrente, allora GetHashCodeè una scelta appropriata. Se stai cercando un checksum persistente , un valore che sarà lo stesso quando eseguirai l'app in un secondo momento, non utilizzarlo GetHashCode, poiché non è garantito che sia lo stesso algoritmo per sempre.
ToolmakerSteve

9

Il modo più sicuro e veloce è usare Bit Masking prima del cast ...

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

Il 0xFFFFFFFFvalore Maschera bit ( ) dipenderà dalla dimensione di Int poiché la dimensione Int dipende dalla macchina.


Devi decidere cosa vuoi che accada quando il risultato traboccerà o diventerà un numero negativo. Quello che mostri continuerà a traboccare, IIRC, perché stai lasciando passare il segno. [Come menzionato in un'altra risposta, nel uncheckedcontesto non si otterrà un overflow - ma non è necessario mascherare uncheckedper evitare l'overflow, quindi una soluzione è necessaria solo nel checkedcontesto.] Esempio per 16 bit. Hold a 16 bit con segno (-32768, 32767). La mascheratura con 0xFFFF consente un valore fino a 65535, causando overflow, IIRC. Potrebbe mascherare per evitare bit di segno, 0x7FFF o 0x7FFFFFFF, se si desidera solo positivo.
ToolmakerSteve

1

Può convertire da

Metodo Convert.ToInt32

Ma genererà una OverflowException se il valore è al di fuori dell'intervallo del tipo Int32. Un test di base ci mostrerà come funziona:

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.

Qui c'è una spiegazione più lunga.


0

non sarebbe

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

essere nel modo corretto, matematicamente parlando?


Ciò bloccherebbe il longValuepiù vicino rappresentabile intse il valore originale è troppo grande. Ma manca lo stesso trattamento di input troppo negativi, che perderebbe invece i bit più significativi; dovresti confrontare Int32.MinValueanche. Il poster originale non sembrava voler essere bloccato, però.
Jeppe Stig Nielsen

A volte IMHO è meglio ottenere un'eccezione rispetto a un valore errato, che Int32.MaxValue sarebbe ...
G. Goncharov,

0

La seguente soluzione verrà troncata in int.MinValue / int.MaxValue se il valore è fuori dai limiti di Integer.

myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)

0

Un modo possibile è utilizzare l'operatore modulo per lasciare che i valori rimangano nell'intervallo int32 e quindi eseguirne il cast in int.

var intValue= (int)(longValue % Int32.MaxValue);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.