воскресенье, 23 марта 2014 г.

Кое-что про числа в .Net

Посмотрите на этот код. Как думаете какой будет результат?

            Double a = 1;
            Double b = 3;
            Double c = a/b;
            Double d = c * 3;

            Single a3 = 1;
            Single b3 = 3;
            Single c3 = a3 / b3;
            Single d3 = c3 * 3;

            decimal a2 = 1;
            decimal b2 = 3;
            decimal c2 = a2 / b2;
            decimal d2 = c2 * 3;

            Console.WriteLine("Double:");
            Console.WriteLine(c.ToString());
            Console.WriteLine(d.ToString());

            Console.WriteLine();
            Console.WriteLine("Single:");
            Console.WriteLine(c3);
            Console.WriteLine(d3);

            Console.WriteLine();
            Console.WriteLine("Decimal:");
            Console.WriteLine(c2);
            Console.WriteLine(d2);

Не смотря на то, что, казалось бы, все три результата должны быть идентичны, только при использовании типа decimal результат такой же как и при обычном делении/умножении на бумажке. И double и single в результате дадут единицу. Почем так получается, спросите вы? Все из-за того, что single и double содержат два дополнительных разряда в конце, благодаря которым можно получить исходное значение при выполнении арифметических действий в обратном порядке. Увидеть их можно вот так:
            Console.WriteLine("{0:R}", c);

На этом, кстати, интересности относительно single и double не заканчиваются как думаете что будет в результате выполнения вот этого кода?
            Double number = 123;
            Double zero = 0;
            Double result = number / zero;



На самом деле исключения "деление на ноль" не будет. В результате выполнения этого кода result будет равно Double.PositiveInfinity. А если -123 разделить на ноль, то Double.NegativeInfinity.

А теперь перейдем к наиболее часто используемому численному типу - Integer. Посмотрите на вот этот код:
            
            int num1 = 10;
            int num2 = 20;

            int num3 = num1 / num2;
            decimal num3_1 = num1 / num2;

Вы уже догадались, что в обоих случаях результат будет равен нулю? А все потому, что при целочисленном делении результат округляется вниз к ближайшему целому. Ну и еще один пример, совсем не очевидный. Как думаете что будет в результате?
            int max = int.MaxValue;
            int res = max + 1;

На самом деле не будет ошибки переполнения. Будет int.MinValue. Все потому, что по умолчанию в C# переполнение int не проверяется и добавление единицы к максимальному значению просто превращает его в минимальное. Если же вы хотите чтобы в случае переполнения получалась ошибка нужно либо включить проверку переполнения в компиляторе, либо сделать вот так:

            checked
            {
                int max = int.MaxValue;
                int res = max + 1;
            }


Комментариев нет:

Отправить комментарий