Chcę przekonwertować long
na int
.
Jeśli wartość long
> int.MaxValue
, z przyjemnością pozwolę jej się zawinąć.
Jaka jest najlepsza droga?
c#
types
int
type-conversion
long-integer
pomimo
źródło
źródło
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.new Random()
używaEnvironment.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, tounchecked
słowo kluczowe (jak pokazano w tej odpowiedzi i komentarzu @ ChrisMarisic itp.) Nie jest potrzebne iint myIntValue = (int)myLongValue
jest dokładnie równoważne. Należy jednak pamiętać, że niezależnie od tego, czy używaszunchecked
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życiechecked(...)
kontekstu, w którym te przypadki rzucą wyjątek.Chociaż nie wiem, co się stanie, gdy będzie większe niż int.MaxValue.
źródło
OverflowException
, a jest to dokładnie to, czego OP nie chce: msdn.microsoft.com/en-us/library/d4haekc4.aspxConvert
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:źródło
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żywajGetHashCode
, 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 ...
Wartość maski bitowej (
0xFFFFFFFF
) będzie zależeć od rozmiaru Int, ponieważ rozmiar Int zależy od maszyny.źródło
unchecked
kontekście nie otrzymasz przepełnienia - ale nie musisz maskować się,unchecked
aby uniknąć przepełnienia, więc rozwiązanie jest potrzebne tylko wchecked
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
Ale zgłosi OverflowException, jeśli wartość jest poza zakresem typu Int32. Podstawowy test pokaże nam, jak to działa:
Tutaj jest dłuższe wyjaśnienie.
źródło
Nie
być właściwą drogą, mówiąc matematycznie?
źródło
longValue
do najbliższego reprezentowanaint
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.Poniższe rozwiązanie spowoduje obcięcie do int.MinValue / int.MaxValue, jeśli wartość wykracza poza granice całkowite.
źródło
Możliwym sposobem jest użycie operatora modulo, aby pozostawić wartości tylko w zakresie int32, a następnie rzutować je na int.
źródło