Odpowiedzi:
Po prostu zrób (int)myLongValue
. Zrobi dokładnie to, co chcesz (odrzucając MSB i biorąc LSB) w unchecked
kontekście (który jest domyślny kompilatora). To będzie rzucać OverflowException
się w checked
kontekście, jeśli wartość nie mieści się w sposób int
:
int myIntValue = unchecked((int)myLongValue);
new Random()
używa Environment.TickCount
pod maską; nie ma potrzeby ręcznego wysiewu z tyknięciem zegara.
unchecked
taki, więc jeśli nie zmieniłeś go wyraźnie, to unchecked
słowo kluczowe (jak pokazano w tej odpowiedzi i komentarzu @ ChrisMarisic itp.) Nie jest potrzebne i int myIntValue = (int)myLongValue
jest dokładnie równoważne. Należy jednak pamiętać, że niezależnie od tego, czy używasz unchecked
słowa kluczowego, czy nie, otrzymujesz niematematyczne, niegrzeczne zachowanie obcinania opisane przez @TJCrowder, w którym znak może się odwrócić w niektórych przypadkach przepełnienia. Jedynym sposobem, aby naprawdę zapewnić matematyczną poprawność, jest użycie checked(...)
kontekstu, w którym te przypadki rzucą wyjątek.
Convert.ToInt32(myValue);
Chociaż nie wiem, co się stanie, gdy będzie większe niż int.MaxValue.
OverflowException
, a jest to dokładnie to, czego OP nie chce: msdn.microsoft.com/en-us/library/d4haekc4.aspx
Convert
nie jest dobre.
if (value > Int32.MaxValue)
return Int32.MaxValue;
else
return Convert.ToInt32( value );
Czasami nie interesuje Cię rzeczywista wartość, ale jej użycie jako suma kontrolna / kod skrótu . W takim przypadku metoda wbudowana GetHashCode()
jest dobrym wyborem:
int checkSumAsInt32 = checkSumAsIn64.GetHashCode();
GetHashCode
jest to właściwy wybór. Jeśli szukasz trwałej sumy kontrolnej - wartości, która będzie taka sama, gdy później uruchomisz aplikację, nie używaj GetHashCode
, ponieważ nie gwarantuje się, że będzie to ten sam algorytm na zawsze.
Najbezpieczniejszym i najszybszym sposobem jest użycie maskowania bitów przed wysłaniem ...
int MyInt = (int) ( MyLong & 0xFFFFFFFF )
Wartość maski bitowej ( 0xFFFFFFFF
) będzie zależeć od rozmiaru Int, ponieważ rozmiar Int zależy od maszyny.
unchecked
kontekście nie otrzymasz przepełnienia - ale nie musisz maskować się, unchecked
aby uniknąć przepełnienia, więc rozwiązanie jest potrzebne tylko w checked
kontekście.] Przykład dla 16-bitów. Podpisane blokady 16-bitowe (-32768, 32767). Maskowanie za pomocą 0xFFFF dopuszcza wartość do 65535, powodując przepełnienie, IIRC. Może maskować, aby uniknąć bitu znaku, 0x7FFF lub 0x7FFFFFFF, jeśli chcesz tylko dodatnie.
Może konwertować według
Convert.ToInt32
Ale zgłosi OverflowException, jeśli wartość jest poza zakresem typu Int32. Podstawowy test pokaże nam, jak to działa:
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.
Tutaj jest dłuższe wyjaśnienie.
Nie
(int) Math.Min(Int32.MaxValue, longValue)
być właściwą drogą, mówiąc matematycznie?
longValue
do najbliższego reprezentowana int
jeśli wartość jest ogromna. Brakuje jednak takiego samego traktowania zbyt ujemnych danych wejściowych, które zamiast tego tracą najbardziej znaczące bity; musiałbyś też porównać Int32.MinValue
. Oryginalny plakat nie wydawał się jednak chcieć zaciskania.
myIntValue
może skończyć się ujemnie, gdymyLongValue
jest dodatnie (4294967294 => -2
) i odwrotnie (-4294967296 => 0
). Na przykład podczas wykonywaniaCompareTo
operacji nie można szczęśliwie rzutować wyniku odejmowania jednegolong
od drugiego na anint
i zwracać to; w przypadku niektórych wartości porównanie dałoby niepoprawny wynik.