В чем разница между литьем long.MaxValue для int и литой float.MaxValue для int?
Я пытаюсь понять разницу между некоторыми типами данных и преобразованием.
public static void ExplicitTypeConversion2()
{
long longValue=long.MaxValue;
float floatValue = float.MaxValue;
int integerValue = (int) longValue;
int integerValue2 = (int)floatValue;
Console.WriteLine(integerValue);
Console.WriteLine(integerValue2);
}
Когда я запускаю этот блок кода, он выводит:
-1
-2147483648
Я знаю, что если значение, которое вы хотите назначить целому числу, больше, чем это целое число может сохранить, оно возвращает минимальное значение integer (-2147483648).
Насколько я знаю, long.MaxValue
намного больше максимального значения целого числа, но если я отбрасываю long.MaxValue
в int
, он возвращает -1.
В чем разница этих двух кастингов? Я думаю, что первый тоже предположил бы вернуть -2147483648 вместо -1.
Ответы
Ответ 1
Позвольте мне объяснить:
long longValue=long.MaxValue;
float floatValue = float.MaxValue;
int integerValue = (int) longValue;
int integerValue2 = (int)floatValue;
Максимальное значение long равно 9,223,372,036,854,775,807 или 0x7FFFFFFFFFFFFFFF, таким образом, 2 дополнения после его уменьшения в 0xFFFFFFFF вернут 0x00000001 со знаком минус-знака, представленным как -1 в десятичной форме.
С другой стороны, максимальное значение float равно 3.40282347E + 38, тем самым лидируя его на int округленное значение до 3E + 38 и используя 2 дополнения после его уменьшения, мы получаем шестнадцатеричное значение 0x80000000 с битом минус-знака, есть -2147483648 в десятичной форме.
Весь этот случай применяется к целым числам со знаком, результат будет отличаться от беззнаковых.
Ссылка:
https://msdn.microsoft.com/en-us/library/system.int64.maxvalue(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.single.maxvalue(v=vs.110).aspx
Ответ 2
если значение, которое вы хотите назначить целому числу, больше, чем это целое число, может сохранять минимальное значение целого числа
Это не правило. Соответствующие правила
Для целых типов в контексте unchecked
(т.е. по умолчанию):
Если тип источника больше, чем тип назначения, то исходное значение усекается на отбрасывая "лишние" наиболее значимые биты. Затем результат обрабатывается как значение адресата тип.
Для float- > int в контексте unchecked
:
Значение округляется до нуля до ближайшего целочисленного значения. Если это целочисленное значение находится внутри диапазон типа назначения, то это значение является результатом преобразования. В противном случае результатом преобразования является неопределенное значение типа назначения.
Отключение 32 старших бит off 0x7fffffffffffffff
дает 0xffffffff
aka -1.
Вам никогда не было обещано, что вы получите int.MinValue
для этого вне диапазона float- > int cast, но все равно, потому что его легко реализовать: инструкция преобразования x64 cvtss2si делает 0x80000000 для результатов вне диапазона и аналогичным образом fistp (старая инструкция преобразования x87, используемая 32-разрядной JIT) сохраняет "целое неопределенное значение", которое 0x80000000.
Ответ 3
Двоичное значение long.MaxValue
равно 0111...111111
(ноль, за которым следуют 63 единицы). При нажатии на int
вы сохраняете самые младшие 32 бита 111...11111
. Это -1
в десятичном формате, поскольку int
- signed
, и применяется два дополнения.