domingo, 14 de julio de 2013

Operaciones de Enteros Especializadas en C#

Tabla de Contenido

0. Introducción
1. División Entera
2. Desbordamiento (Overflow) de Enteros
3. Operador de Chequeo para Desbordamiento de Aritmética de Enteros
4. Chequeo de Desbordamiento para Expresiones Constantes
5. Conclusiones
6. Glosario
7. Referencias

Introducción

Ahora veremos ciertas operaciones especializadas interesantes cuando tratamos con tipos de datos numéricos enteros: división entera, desbordamiento de aritmética sobre enteros, y algunos operadores que nos ayudan a controlar y preveer posibles errores en los cálculos aritméticos que hagamos en nuestras aplicaciones.

1. División Entera

Siempre que realicemos una operación entre dos números enteros el resultado será un número del mismo tipo, es decir, entero. El residuo (o módulo) se trunca (i.e., se redondea a cero).

Ahora, si quisiéramos dividir por una variable cuyo valor es cero (0), se generará un error en tiempo de ejecución. La excepción que produce este error es DivideByZeroException [1]. Precisamente está excepción es detectada y lanzada por la CLR durante la ejecución del programa.

int a = 2 / 3; // 0

int b = 0;
int c = 5 / b; // lanza la excepción DivideByZeroException

Lo anterior también ocurre cuando dividimos entre una literal o la constante cero (0).

2. Desbordamiento (Overflow) de Enteros

Tanto en tiempo de compilación como en tiempo de ejecución, las operaciones sobre enteros pueden producir sobrecarga. Por defecto, la sobrecarga ocurre de manera silenciosa: la CLR no lanza ninguna excepción y el resultado presenta un comportamiento envolvente, debido a que el cómputo del valor se realiza con tipos de mayor capacidad numérica y los bits significativos restantes son descartados.

Veamos esto con un ejemplo sencillo del desbordamiento al decrementar el valor posible de int:

int a = int.MinValue;
a--;
Console.WriteLine(a==int.MaxValue); // true

Cuando se declara la variable a el valor que se le asigna corresponde con el valor mínimo soportable por el tipo de dato int (Int32), es decir, -2.147.483.648. Luego cuando ocurre a--; ocurre un desbordamiento y el valor de a será el valor máximo del tipo int: 2.147.483.647. En [1] llaman a este comportamiento como envolvente.

3. Operador de Chequeo para Desbordamiento de Aritmética de Enteros

El operador checked [6] permite chequear si una expresión produce desbordamiento. Esto nos ayuda detectar posibles errores en las expresiones aritméticas que contengan tipos de datos enteros.

El operador check afecta expresiones que contengan uno de estos operadores: ++, --, +, - (unarios y binarios), *, /, y operadores que contengan conversiones explícitas entre tipos enteros.

También es necesario apuntar, que si tenemos dos literales o constantes que desbordan (el valor está por fuera del rango del tipo del destino) la capacidad numérica del tipo de dato. Veamos que ocurre en Visual Studio si intentamos sumar dos literales que son equivalentes al valor máximo del tipo int: 2.147.483.647:
int overflow
Figura 1. Desebordamiento de constantes enteras.
El mensaje de error "The operation overflows at compile time in checked mode" nos está informando acerca del desbordamiento que ocurrirá en tiempo de compilación mientras que la opción /checked+ sea pasada al compilador de C# (csc.exe).

Nota

El operador checked no tienen ningún efecto sobre los tipos numéricos float y double. Esto se debe a que estos tipos se desbordan a valores "infinitos" espaciales. Tampoco tiene efecto sobre el tipo decimal, ya que éste posee la capacidad de tipo chequeado.

Ahora pasemos a escribir código de ejemplo (SinOperadorChecked) para demostrar la utilidad de este operador. Para el primer caso:

Archivo C# SinOperadorChecked.cs [Enlace alternativo]:

Ahora si creamos la clase UsoOperadorChecked para demostrar las capacidades del operador checked como parte de una expresión o como bloque de código:

Archivo C# UsoOperadorChecked.cs [Enlace alternativo]:


Cuando ejecutemos este programa (desde la línea de comandos) se generará la excepción System.OverflowException [8]:
System.OverflowException en línea de comandos
Figura 2. System.OverflowException al Ejecutar UsoOperadorChecked.
Si ahora ejecutamos el programa en Visual Studio, obtendremos:
System.OverflowException en VisualStudio
Figura 3. OverflowException reportada en Visual Studio 2012.
Básicamente la excepción que reporta la CLR consiste en una operación aritmética que produce desbordamiento sobre los tipos de datos. Esta es precisamente la utilidad del operador checked en sentencias y bloques de código.

Existen otras formas de comprobar el desbordamiento de enteros:
  • Con la opción /checked+ desde la línea de comandos.
  • Sobre Advanced Build Settings en Visual Studio.
Para deshabilitar el chequeo sobre ciertas sentencias o expresiones, lo puede hacer a través del operador unchecked. Por ejemplo, en las líneas de código siguiente no se generará ninguna excepción, inclusive si la compilación se inicia con la opción /checked+:

int x = int.MaxValue;
int y = unchecked( x + 1 );
unchecked{ int z = x + 1; }

4. Chequeo de Desbordamiento para Expresiones Constantes

El operador unchecked es útil cuando deseemos evitar la detección de desbordamiento en tiempo de compilación:

int x = int.MaxValue + 1; // Error tiempo de compilación
int y = unchecked( int.MaxValue + 1 ); // No hay ningún error

5. Conclusiones

Estas operaciones especializadas de los tipos numéricos enteros que hemos visto a lo largo de este artículo nos presenta información acerca del desbordamiento de datos numéricos enteros en operaciones aritméticas, además, de cómo prevenirlas con el operador checked.

6. Glosario

- Desbordamiento
- Excepción
- Overflow

7. Referencias

[1] C# DivideByZeroException - http://www.dotnetperls.com/dividebyzeroexception
[3] What does stack overflow mean - http://wiki.answers.com/Q/What_does_stack_overflow_mean
[6] checked (C# Reference) - http://msdn.microsoft.com/en-us/library/74b4xzyw(v=vs.110).aspx
[7] C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[8] OverflowException Class (System) - http://msdn.microsoft.com/en-us/library/system.overflowexception(v=vs.11).aspx


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.