В чем разница между литьем 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, и применяется два дополнения.