Capítulo 4: Operaciones y expresiones en C#

5 min de lectura

Parte I - Sección 1: Fundamentos de C# - Nivel: Principiante


Objetivos de aprendizaje

Al finalizar este capítulo serás capaz de:

  • Usar operadores aritméticos avanzados para cálculos complejos
  • Aplicar operadores de comparación para evaluar condiciones
  • Combinar operadores lógicos para expresiones complejas
  • Entender la precedencia de operadores en expresiones
  • Construir expresiones matemáticas complejas para ingeniería eléctrica

Requisitos previos

Antes de comenzar este capítulo debes:

  • Haber completado el Capítulo 3
  • Entender qué son las variables
  • Conocer los tipos básicos (int, double, string, bool)
  • Saber declarar y asignar valores a variables

Proyecto del capítulo

Sistema de Verificación de Instalación Eléctrica

Al final de este capítulo habrás construido un script que:

  • Verifica si un circuito cumple con normas técnicas
  • Compara valores medidos con límites permitidos
  • Calcula caídas de tensión y las valida
  • Genera reportes de conformidad con múltiples condiciones

Tiempo estimado: 40-50 minutos


Contenido

1. Introducción: De cálculos simples a expresiones complejas

En el capítulo anterior vimos operaciones básicas:

double resistencia = voltaje / corriente;
double potencia = voltaje * corriente;

En este capítulo aprenderás a construir expresiones más complejas que combinan múltiples operaciones y condiciones, como las que usas en ingeniería:

  • Verificar rangos: ¿El voltaje está entre 207V y 253V? (230V ±10%)
  • Validar condiciones: ¿La caída de tensión es menor al 3% Y la corriente no excede el límite?
  • Cálculos complejos: Potencia trifásica, factor de corrección, dimensionado de cables

2. Operadores aritméticos avanzados

Ya conoces los básicos: +, -, *, /. Veamos operadores adicionales y técnicas útiles.

2.1 Módulo (%) - Resto de división

El operador módulo % devuelve el resto de una división entera.

int total = 17;
int grupo = 5;
int resto = total % grupo;  // 2 (17 ÷ 5 = 3 con resto 2)

Casos prácticos:

Ejemplo 1: Detectar si un número es par o impar

int numeroCable = 24;
int resto = numeroCable % 2;

if (resto == 0)
{
    // Es par
}
else
{
    // Es impar
}

Ejemplo 2: Distribuir cables en bandejas

int totalCables = 47;
int capacidadBandeja = 12;

int bandejasCompletas = totalCables / capacidadBandeja;  // 3
int cablesEnUltimaBandeja = totalCables % capacidadBandeja;  // 11

// Necesitas 4 bandejas (3 completas + 1 parcial)

2.2 Operadores de incremento y decremento

Para aumentar o disminuir una variable en 1:

int contador = 10;

contador++;  // contador = contador + 1  →  11
contador--;  // contador = contador - 1  →  10

Dos formas: prefijo y postfijo

int a = 5;
int b = ++a;  // Primero incrementa, luego asigna: a=6, b=6

int c = 5;
int d = c++;  // Primero asigna, luego incrementa: c=6, d=5

En la práctica, úsalos en líneas separadas para claridad:

int erroresEncontrados = 0;

// Encontraste un error
erroresEncontrados++;

// Encontraste otro
erroresEncontrados++;

// erroresEncontrados ahora es 2

2.3 Operadores de asignación compuesta

Atajos para operaciones frecuentes:

int cantidad = 10;

cantidad += 5;   // cantidad = cantidad + 5  →  15
cantidad -= 3;   // cantidad = cantidad - 3  →  12
cantidad *= 2;   // cantidad = cantidad * 2  →  24
cantidad /= 4;   // cantidad = cantidad / 4  →  6
cantidad %= 5;   // cantidad = cantidad % 5  →  1

Ejemplo práctico: Acumular valores

double potenciaTotal = 0.0;

double motor1 = 7.5;   // kW
double motor2 = 11.0;  // kW
double motor3 = 5.5;   // kW

potenciaTotal += motor1;  // 7.5
potenciaTotal += motor2;  // 18.5
potenciaTotal += motor3;  // 24.0 kW

2.4 Potencias y raíces (Math)

Para operaciones matemáticas avanzadas, usa la clase Math:

// Potencia: Math.Pow(base, exponente)
double area = Math.Pow(5, 2);  // 5² = 25

// Raíz cuadrada
double lado = Math.Sqrt(25);  // √25 = 5

// Raíz cúbica (elevar a 1/3)
double volumen = 27;
double arista = Math.Pow(volumen, 1.0/3.0);  // ∛27 = 3

Caso práctico: Cálculo de potencia trifásica

double voltaje = 400.0;        // V línea-línea
double corriente = 50.0;       // A
double factorPotencia = 0.85;

// P = √3 × V × I × cos φ
double potencia = Math.Sqrt(3) * voltaje * corriente * factorPotencia;
// 29,527 W ≈ 29.5 kW

Otras funciones útiles:

Math.Abs(-15.5);      // Valor absoluto: 15.5
Math.Round(15.678);   // Redondeo: 16
Math.Round(15.678, 2); // Redondeo 2 decimales: 15.68
Math.Ceiling(15.1);   // Redondeo hacia arriba: 16
Math.Floor(15.9);     // Redondeo hacia abajo: 15
Math.Max(10, 20);     // Máximo: 20
Math.Min(10, 20);     // Mínimo: 10

3. Operadores de comparación

Comparan dos valores y devuelven un bool (true o false).

OperadorSignificadoEjemploResultado
==Igual a5 == 5true
!=Diferente de5 != 3true
>Mayor que10 > 5true
<Menor que10 < 5false
>=Mayor o igual10 >= 10true
<=Menor o igual10 <= 5false

Ejemplos prácticos:

double voltajeMedido = 235.5;
double voltajeNominal = 230.0;

bool voltajeMayor = voltajeMedido > voltajeNominal;  // true
bool voltajeIgual = voltajeMedido == voltajeNominal; // false
bool volajeDiferente = voltajeMedido != voltajeNominal; // true

Uso típico: Verificar límites

double corriente = 18.5;
double corrienteMaxima = 16.0;

bool excedeLimite = corriente > corrienteMaxima;  // true

if (excedeLimite)
{
    MessageBox.Show("¡ADVERTENCIA! Corriente excede el límite.");
}

Importante con double: No uses == para comparar decimales

double a = 0.1 + 0.2;  // 0.30000000000000004
double b = 0.3;

bool sonIguales = (a == b);  // Puede ser false debido a precisión

// Mejor: compara con tolerancia
double tolerancia = 0.0001;
bool sonIgualesAprox = Math.Abs(a - b) < tolerancia;  // true

4. Operadores lógicos

Combinan múltiples condiciones booleanas.

4.1 AND lógico (&&) - "Y"

true solo si ambas condiciones son verdaderas.

bool condicion1 = true;
bool condicion2 = true;
bool resultado = condicion1 && condicion2;  // true

Tabla de verdad:

ABA && B
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

Ejemplo práctico: Verificar rango de voltaje

double voltaje = 235.0;
double minimo = 207.0;  // 230V - 10%
double maximo = 253.0;  // 230V + 10%

bool dentroRango = (voltaje >= minimo) && (voltaje <= maximo);  // true

Otro ejemplo: Validar circuito completo

double corriente = 15.5;
double corrienteMaxima = 16.0;
double caidaTension = 5.2;
double caidaMaxima = 6.9;  // 3% de 230V

bool circuitoOK = (corriente <= corrienteMaxima) && (caidaTension <= caidaMaxima);
// true (ambas condiciones se cumplen)

4.2 OR lógico (||) - "O"

true si al menos una condición es verdadera.

bool condicion1 = true;
bool condicion2 = false;
bool resultado = condicion1 || condicion2;  // true

Tabla de verdad:

ABA || B
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

Ejemplo práctico: Detectar situaciones anormales

double voltaje = 195.0;
double corriente = 18.5;

bool voltajeBajo = voltaje < 207.0;
bool corrienteAlta = corriente > 16.0;

bool requiereAtencion = voltajeBajo || corrienteAlta;  // true
// (cualquiera de las dos condiciones anormales activa la alerta)

4.3 NOT lógico (!) - "NO"

Invierte el valor booleano.

bool proyectoAbierto = true;
bool proyectoCerrado = !proyectoAbierto;  // false

Ejemplos prácticos:

bool tieneErrores = false;
bool estaLimpio = !tieneErrores;  // true

bool esTrifasico = true;
bool esMonofasico = !esTrifasico;  // false

Uso común: Verificar negaciones

bool backupRealizado = false;

if (!backupRealizado)
{
    MessageBox.Show("Advertencia: No se ha realizado backup.");
}

4.4 Combinando operadores lógicos

Puedes combinar múltiples operadores:

double voltaje = 235.0;
double corriente = 15.0;
double temperatura = 45.0;

bool voltajeOK = (voltaje >= 207.0) && (voltaje <= 253.0);
bool corrienteOK = corriente <= 16.0;
bool temperaturaOK = temperatura <= 50.0;

bool sistemaOK = voltajeOK && corrienteOK && temperaturaOK;  // true

Con OR y AND:

// Alerta si: voltaje fuera de rango O corriente alta
bool alerta = (voltaje < 207.0 || voltaje > 253.0) || (corriente > 16.0);

5. Precedencia de operadores

Cuando combinas múltiples operadores, C# los evalúa en un orden específico.

5.1 Orden de precedencia (de mayor a menor)

  1. Paréntesis ( )
  2. Incremento/Decremento ++, --
  3. Unarios !, - (negación)
  4. Multiplicación, División, Módulo *, /, %
  5. Suma, Resta +, -
  6. Comparación <, >, <=, >=
  7. Igualdad ==, !=
  8. AND lógico &&
  9. OR lógico ||
  10. Asignación =, +=, -=, etc.

5.2 Ejemplos de precedencia

int resultado = 5 + 3 * 2;  // 11, no 16
// Porque * tiene mayor precedencia que +
// Equivale a: 5 + (3 * 2)
int resultado = (5 + 3) * 2;  // 16
// Los paréntesis fuerzan el orden

Con operadores lógicos:

bool resultado = true || false && false;  // true
// && tiene mayor precedencia que ||
// Equivale a: true || (false && false)
// Equivale a: true || false
// Resultado: true
bool resultado = (true || false) && false;  // false
// Paréntesis cambian el orden

5.3 Buenas prácticas

Siempre usa paréntesis cuando tengas dudas o cuando mejore la legibilidad:

// Poco claro
bool ok = voltaje > 207 && voltaje < 253 || corriente < 16;

// Claro con paréntesis
bool ok = ((voltaje > 207) && (voltaje < 253)) || (corriente < 16);

Ejemplo práctico bien estructurado:

double voltaje = 235.0;
double corriente = 15.5;
double caidaTension = 5.0;

bool voltajeDentroRango = (voltaje >= 207.0) && (voltaje <= 253.0);
bool corrienteSegura = (corriente <= 16.0);
bool caidaTensionAceptable = (caidaTension <= 6.9);

bool instalacionCorrecta = voltajeDentroRango && corrienteSegura && caidaTensionAceptable;

Este estilo:

  • Es fácil de leer
  • Es fácil de depurar
  • Es fácil de modificar

6. Expresiones complejas en ingeniería eléctrica

Veamos cómo construir expresiones reales que usarías en proyectos.

6.1 Verificar rango de voltaje (±10%)

double voltajeNominal = 230.0;
double voltajeMedido = 235.5;
double tolerancia = 0.10;  // 10%

double minimo = voltajeNominal * (1 - tolerancia);  // 207V
double maximo = voltajeNominal * (1 + tolerancia);  // 253V

bool voltajeOK = (voltajeMedido >= minimo) && (voltajeMedido <= maximo);

6.2 Calcular y validar caída de tensión

// Datos del cable
double longitudMetros = 50.0;
double corrienteAmperios = 16.0;
double seccionMM2 = 2.5;
double resistividadCobre = 0.018;

// Cálculo de caída de tensión
double caidaTension = (2 * longitudMetros * corrienteAmperios * resistividadCobre) / seccionMM2;

// Validar contra límite del 3%
double voltajeNominal = 230.0;
double caidaMaximaPermitida = voltajeNominal * 0.03;  // 6.9V

bool caidaAceptable = caidaTension <= caidaMaximaPermitida;
double porcentajeCaida = (caidaTension / voltajeNominal) * 100;

6.3 Dimensionar cable por corriente admisible

double corrienteCircuito = 32.0;  // A
double factorTemperatura = 0.94;
double factorAgrupacion = 0.80;

// Corriente corregida que debe soportar el cable
double corrienteCorregida = corrienteCircuito / (factorTemperatura * factorAgrupacion);

// ¿Cable de 6mm² (43A) es suficiente?
double corrienteAdmisible6mm = 43.0;
bool cable6mmSuficiente = corrienteAdmisible6mm >= corrienteCorregida;

// ¿Cable de 4mm² (36A) es suficiente?
double corrienteAdmisible4mm = 36.0;
bool cable4mmSuficiente = corrienteAdmisible4mm >= corrienteCorregida;

6.4 Factor de potencia y potencia reactiva

double potenciaActiva = 15000.0;    // W
double factorPotencia = 0.75;

// Calcular potencia aparente: S = P / cos φ
double potenciaAparente = potenciaActiva / factorPotencia;  // 20000 VA

// Calcular potencia reactiva: Q = √(S² - P²)
double potenciaReactiva = Math.Sqrt(
    Math.Pow(potenciaAparente, 2) - Math.Pow(potenciaActiva, 2)
);  // 13229 VAr

// ¿Factor de potencia aceptable? (mínimo 0.92)
bool fpAceptable = factorPotencia >= 0.92;

// Capacitor necesario para corregir a 0.92
double factorPotenciaObjetivo = 0.92;
double anguloActual = Math.Acos(factorPotencia);
double anguloObjetivo = Math.Acos(factorPotenciaObjetivo);
double potenciaCapacitor = potenciaActiva * (Math.Tan(anguloActual) - Math.Tan(anguloObjetivo));

Manos a la obra: Construyendo el proyecto

Vamos a crear un Sistema de Verificación de Instalación Eléctrica que valida múltiples parámetros.

Paso 1: Estructura básica y datos de entrada

using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;

public class VerificacionInstalacion
{
    [Start]
    public void Ejecutar()
    {
        // ========================================
        // DATOS DE LA INSTALACIÓN
        // ========================================

        string nombreCircuito = "Circuito Taller - Línea 3";

        // Parámetros eléctricos medidos
        double voltajeMedido = 225.0;        // V
        double corrienteMedida = 14.8;       // A
        double factorPotencia = 0.88;

        // Datos del cable instalado
        double longitudCable = 45.0;         // m
        double seccionCable = 2.5;           // mm²
        double corrienteAdmisible = 21.0;    // A (tabla para 2.5mm²)

        // Límites normativos
        double voltajeNominal = 230.0;       // V
        double corrienteCircuito = 16.0;     // A (protección)
        double toleranciaVoltaje = 0.10;     // 10%
        double caidaMaximaPorcentaje = 0.03; // 3%
        double factorPotenciaMinimo = 0.85;
    }
}

¿Qué acabamos de hacer? Definimos todos los parámetros que vamos a verificar en una instalación real.


Paso 2: Verificación de voltaje

// ========================================
// VERIFICACIÓN 1: RANGO DE VOLTAJE
// ========================================

double voltajeMinimo = voltajeNominal * (1 - toleranciaVoltaje);
double voltajeMaximo = voltajeNominal * (1 + toleranciaVoltaje);

bool voltajeOK = (voltajeMedido >= voltajeMinimo) && (voltajeMedido <= voltajeMaximo);

string resultadoVoltaje;
if (voltajeOK)
{
    resultadoVoltaje = string.Format("OK ({0:F1}V está entre {1:F1}V y {2:F1}V)",
        voltajeMedido, voltajeMinimo, voltajeMaximo);
}
else
{
    resultadoVoltaje = string.Format("FALLO ({0:F1}V fuera del rango {1:F1}V - {2:F1}V)",
        voltajeMedido, voltajeMinimo, voltajeMaximo);
}

¿Qué acabamos de hacer? Verificamos que el voltaje medido esté dentro del rango ±10% del nominal.


Paso 3: Verificación de corriente

// ========================================
// VERIFICACIÓN 2: CORRIENTE
// ========================================

bool corrienteOK = (corrienteMedida <= corrienteCircuito);

string resultadoCorriente;
if (corrienteOK)
{
    double porcentajeUso = (corrienteMedida / corrienteCircuito) * 100;
    resultadoCorriente = string.Format("OK ({0:F1}A / {1:F1}A = {2:F1}% de uso)",
        corrienteMedida, corrienteCircuito, porcentajeUso);
}
else
{
    resultadoCorriente = string.Format("FALLO ({0:F1}A excede límite de {1:F1}A)",
        corrienteMedida, corrienteCircuito);
}

Paso 4: Cálculo y verificación de caída de tensión

// ========================================
// VERIFICACIÓN 3: CAÍDA DE TENSIÓN
// ========================================

double resistividadCobre = 0.018;  // Ω·mm²/m

double caidaTension = (2 * longitudCable * corrienteMedida * resistividadCobre) / seccionCable;
double porcentajeCaida = (caidaTension / voltajeNominal) * 100;
double caidaMaximaVoltios = voltajeNominal * caidaMaximaPorcentaje;

bool caidaTensionOK = (caidaTension <= caidaMaximaVoltios);

string resultadoCaida;
if (caidaTensionOK)
{
    resultadoCaida = string.Format("OK ({0:F2}V = {1:F2}% < {2:F2}%)",
        caidaTension, porcentajeCaida, caidaMaximaPorcentaje * 100);
}
else
{
    resultadoCaida = string.Format("FALLO ({0:F2}V = {1:F2}% > {2:F2}%)",
        caidaTension, porcentajeCaida, caidaMaximaPorcentaje * 100);
}

¿Qué acabamos de hacer? Calculamos la caída de tensión en el cable y verificamos que esté bajo el 3%.


Paso 5: Verificación de factor de potencia

// ========================================
// VERIFICACIÓN 4: FACTOR DE POTENCIA
// ========================================

bool factorPotenciaOK = (factorPotencia >= factorPotenciaMinimo);

string resultadoFP;
if (factorPotenciaOK)
{
    resultadoFP = string.Format("OK ({0:F2} >= {1:F2})",
        factorPotencia, factorPotenciaMinimo);
}
else
{
    resultadoFP = string.Format("BAJO ({0:F2} < {1:F2})",
        factorPotencia, factorPotenciaMinimo);
}

Paso 6: Verificación de dimensionado de cable

// ========================================
// VERIFICACIÓN 5: DIMENSIONADO CABLE
// ========================================

bool cableDimensionadoOK = (corrienteAdmisible >= corrienteMedida);

string resultadoCable;
if (cableDimensionadoOK)
{
    double margenSeguridad = ((corrienteAdmisible - corrienteMedida) / corrienteAdmisible) * 100;
    resultadoCable = string.Format("OK ({0}mm² soporta {1:F1}A, medido {2:F1}A, margen {3:F1}%)",
        seccionCable, corrienteAdmisible, corrienteMedida, margenSeguridad);
}
else
{
    resultadoCable = string.Format("FALLO ({0}mm² solo soporta {1:F1}A, medido {2:F1}A)",
        seccionCable, corrienteAdmisible, corrienteMedida);
}

Paso 7: Evaluación general y construcción del mensaje

// ========================================
// EVALUACIÓN GENERAL
// ========================================

bool instalacionConforme = voltajeOK && corrienteOK && caidaTensionOK &&
                           factorPotenciaOK && cableDimensionadoOK;

string estadoGeneral = instalacionConforme ? "CONFORME" : "NO CONFORME";

// ========================================
// CONSTRUCCIÓN DEL REPORTE
// ========================================

string reporte = string.Format(
    "=== VERIFICACIÓN DE INSTALACIÓN ELÉCTRICA ===\n\n" +
    "Circuito: {0}\n" +
    "Estado: {1}\n\n" +
    "RESULTADOS:\n\n" +
    "1. Voltaje: {2}\n" +
    "2. Corriente: {3}\n" +
    "3. Caída tensión: {4}\n" +
    "4. Factor potencia: {5}\n" +
    "5. Dimensionado cable: {6}\n\n" +
    "DATOS TÉCNICOS:\n" +
    "- Cable: {7}mm², {8}m\n" +
    "- Potencia activa: {9:F2} W\n" +
    "- Potencia aparente: {10:F2} VA",
    nombreCircuito,
    estadoGeneral,
    resultadoVoltaje,
    resultadoCorriente,
    resultadoCaida,
    resultadoFP,
    resultadoCable,
    seccionCable,
    longitudCable,
    voltajeMedido * corrienteMedida * factorPotencia,
    voltajeMedido * corrienteMedida
);

// ========================================
// MOSTRAR REPORTE
// ========================================

MessageBoxIcon icono = instalacionConforme ? MessageBoxIcon.Information : MessageBoxIcon.Warning;

MessageBox.Show(reporte, "Verificación de Instalación", MessageBoxButtons.OK, icono);

¿Qué acabamos de hacer? Combinamos todos los resultados en un reporte completo y mostramos un icono diferente según el resultado.


Código completo del proyecto

using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;

public class VerificacionInstalacion
{
    [Start]
    public void Ejecutar()
    {
        // ========================================
        // DATOS DE LA INSTALACIÓN
        // ========================================

        string nombreCircuito = "Circuito Taller - Línea 3";

        // Parámetros eléctricos medidos
        double voltajeMedido = 225.0;        // V
        double corrienteMedida = 14.8;       // A
        double factorPotencia = 0.88;

        // Datos del cable instalado
        double longitudCable = 45.0;         // m
        double seccionCable = 2.5;           // mm²
        double corrienteAdmisible = 21.0;    // A (tabla para 2.5mm²)

        // Límites normativos
        double voltajeNominal = 230.0;       // V
        double corrienteCircuito = 16.0;     // A (protección)
        double toleranciaVoltaje = 0.10;     // 10%
        double caidaMaximaPorcentaje = 0.03; // 3%
        double factorPotenciaMinimo = 0.85;

        // ========================================
        // VERIFICACIÓN 1: RANGO DE VOLTAJE
        // ========================================

        double voltajeMinimo = voltajeNominal * (1 - toleranciaVoltaje);
        double voltajeMaximo = voltajeNominal * (1 + toleranciaVoltaje);

        bool voltajeOK = (voltajeMedido >= voltajeMinimo) && (voltajeMedido <= voltajeMaximo);

        string resultadoVoltaje;
        if (voltajeOK)
        {
            resultadoVoltaje = string.Format("OK ({0:F1}V está entre {1:F1}V y {2:F1}V)",
                voltajeMedido, voltajeMinimo, voltajeMaximo);
        }
        else
        {
            resultadoVoltaje = string.Format("FALLO ({0:F1}V fuera del rango {1:F1}V - {2:F1}V)",
                voltajeMedido, voltajeMinimo, voltajeMaximo);
        }

        // ========================================
        // VERIFICACIÓN 2: CORRIENTE
        // ========================================

        bool corrienteOK = (corrienteMedida <= corrienteCircuito);

        string resultadoCorriente;
        if (corrienteOK)
        {
            double porcentajeUso = (corrienteMedida / corrienteCircuito) * 100;
            resultadoCorriente = string.Format("OK ({0:F1}A / {1:F1}A = {2:F1}% de uso)",
                corrienteMedida, corrienteCircuito, porcentajeUso);
        }
        else
        {
            resultadoCorriente = string.Format("FALLO ({0:F1}A excede límite de {1:F1}A)",
                corrienteMedida, corrienteCircuito);
        }

        // ========================================
        // VERIFICACIÓN 3: CAÍDA DE TENSIÓN
        // ========================================

        double resistividadCobre = 0.018;  // Ω·mm²/m

        double caidaTension = (2 * longitudCable * corrienteMedida * resistividadCobre) / seccionCable;
        double porcentajeCaida = (caidaTension / voltajeNominal) * 100;
        double caidaMaximaVoltios = voltajeNominal * caidaMaximaPorcentaje;

        bool caidaTensionOK = (caidaTension <= caidaMaximaVoltios);

        string resultadoCaida;
        if (caidaTensionOK)
        {
            resultadoCaida = string.Format("OK ({0:F2}V = {1:F2}% < {2:F2}%)",
                caidaTension, porcentajeCaida, caidaMaximaPorcentaje * 100);
        }
        else
        {
            resultadoCaida = string.Format("FALLO ({0:F2}V = {1:F2}% > {2:F2}%)",
                caidaTension, porcentajeCaida, caidaMaximaPorcentaje * 100);
        }

        // ========================================
        // VERIFICACIÓN 4: FACTOR DE POTENCIA
        // ========================================

        bool factorPotenciaOK = (factorPotencia >= factorPotenciaMinimo);

        string resultadoFP;
        if (factorPotenciaOK)
        {
            resultadoFP = string.Format("OK ({0:F2} >= {1:F2})",
                factorPotencia, factorPotenciaMinimo);
        }
        else
        {
            resultadoFP = string.Format("BAJO ({0:F2} < {1:F2})",
                factorPotencia, factorPotenciaMinimo);
        }

        // ========================================
        // VERIFICACIÓN 5: DIMENSIONADO CABLE
        // ========================================

        bool cableDimensionadoOK = (corrienteAdmisible >= corrienteMedida);

        string resultadoCable;
        if (cableDimensionadoOK)
        {
            double margenSeguridad = ((corrienteAdmisible - corrienteMedida) / corrienteAdmisible) * 100;
            resultadoCable = string.Format("OK ({0}mm² soporta {1:F1}A, medido {2:F1}A, margen {3:F1}%)",
                seccionCable, corrienteAdmisible, corrienteMedida, margenSeguridad);
        }
        else
        {
            resultadoCable = string.Format("FALLO ({0}mm² solo soporta {1:F1}A, medido {2:F1}A)",
                seccionCable, corrienteAdmisible, corrienteMedida);
        }

        // ========================================
        // EVALUACIÓN GENERAL
        // ========================================

        bool instalacionConforme = voltajeOK && corrienteOK && caidaTensionOK &&
                                   factorPotenciaOK && cableDimensionadoOK;

        string estadoGeneral = instalacionConforme ? "CONFORME" : "NO CONFORME";

        // ========================================
        // CONSTRUCCIÓN DEL REPORTE
        // ========================================

        string reporte = string.Format(
            "=== VERIFICACIÓN DE INSTALACIÓN ELÉCTRICA ===\n\n" +
            "Circuito: {0}\n" +
            "Estado: {1}\n\n" +
            "RESULTADOS:\n\n" +
            "1. Voltaje: {2}\n" +
            "2. Corriente: {3}\n" +
            "3. Caída tensión: {4}\n" +
            "4. Factor potencia: {5}\n" +
            "5. Dimensionado cable: {6}\n\n" +
            "DATOS TÉCNICOS:\n" +
            "- Cable: {7}mm², {8}m\n" +
            "- Potencia activa: {9:F2} W\n" +
            "- Potencia aparente: {10:F2} VA",
            nombreCircuito,
            estadoGeneral,
            resultadoVoltaje,
            resultadoCorriente,
            resultadoCaida,
            resultadoFP,
            resultadoCable,
            seccionCable,
            longitudCable,
            voltajeMedido * corrienteMedida * factorPotencia,
            voltajeMedido * corrienteMedida
        );

        // ========================================
        // MOSTRAR REPORTE
        // ========================================

        MessageBoxIcon icono = instalacionConforme ? MessageBoxIcon.Information : MessageBoxIcon.Warning;

        MessageBox.Show(reporte, "Verificación de Instalación", MessageBoxButtons.OK, icono);
    }
}

Deep Dive: Entendiendo en profundidad

Evaluación de cortocircuito (short-circuit evaluation)

Los operadores && y || son "perezosos": si el resultado ya es obvio, no evalúan el resto.

Con AND (&&):

bool a = false;
bool b = ExpresionCompleja();  // Esta función NO se ejecutará

bool resultado = a && b;  // false (porque a ya es false)

Si a es false, el resultado siempre será false, así que C# no evalúa b.

Con OR (||):

bool a = true;
bool b = ExpresionCompleja();  // Esta función NO se ejecutará

bool resultado = a || b;  // true (porque a ya es true)

Uso práctico: Evitar errores de división por cero

double divisor = 0;
double dividendo = 10;

// Peligroso: siempre divide, puede dar error
if (dividendo / divisor > 5) { }  // ERROR: divide por cero

// Seguro: solo divide si divisor != 0
if (divisor != 0 && (dividendo / divisor > 5))
{
    // Solo entra aquí si divisor != 0
}

Operadores bit a bit

Para manipulación de bits (poco común en EPLAN, pero útil para flags):

int a = 5;   // 0101 en binario
int b = 3;   // 0011 en binario

int andBit = a & b;   // 0001 = 1
int orBit = a | b;    // 0111 = 7
int xorBit = a ^ b;   // 0110 = 6
int notBit = ~a;      // 1010 (invertido)

Uso práctico: Trabajar con flags de EPLAN (lo veremos en capítulos avanzados).

Operador de coalescencia nula (??)

Para valores que pueden ser null:

string nombreProyecto = ObtenerNombre();  // Puede devolver null

string nombreFinal = nombreProyecto ?? "Sin nombre";
// Si nombreProyecto es null, usa "Sin nombre"

Equivalente a:

string nombreFinal;
if (nombreProyecto != null)
{
    nombreFinal = nombreProyecto;
}
else
{
    nombreFinal = "Sin nombre";
}

Mejores prácticas con expresiones

1. Divide expresiones complejas en pasos

// Mal: difícil de leer y depurar
bool ok = (v >= vMin && v <= vMax) && (i <= iMax) && ((2*l*i*r)/s <= vMax*0.03);

// Bien: cada verificación es clara
bool voltajeOK = (voltaje >= voltajeMinimo) && (voltaje <= voltajeMaximo);
bool corrienteOK = (corriente <= corrienteMaxima);
double caidaTension = (2 * longitud * corriente * resistividad) / seccion;
bool caidaOK = (caidaTension <= voltajeMaximo * 0.03);

bool todoOK = voltajeOK && corrienteOK && caidaOK;

2. Usa variables intermedias con nombres descriptivos

// Mal
double x = (v * i * 1.732 * 0.85) / 1000;

// Bien
double voltaje = 400.0;
double corriente = 50.0;
double raizDeTres = 1.732;
double factorPotencia = 0.85;
double potenciaKW = (voltaje * corriente * raizDeTres * factorPotencia) / 1000;
// O mejor aún:
double potenciaKW = (voltaje * corriente * Math.Sqrt(3) * factorPotencia) / 1000;

3. Comenta fórmulas complejas

// Sección mínima de cable según ITC-BT-19
// S = (2 * L * I) / (γ * ΔU)
// donde: γ = conductividad (56 m/Ω·mm² para Cu)
//        ΔU = caída de tensión admisible
double seccionMinima = (2 * longitudMetros * corrienteAmperios) /
                       (56 * caidaTensionAdmisible);

Errores comunes

Error 1: Confundir = con ==

Síntoma: Asignación en lugar de comparación.

int voltaje = 230;

if (voltaje = 400)  // ERROR: asignación, no comparación
{
    // Este bloque siempre se ejecuta
}

Solución:

if (voltaje == 400)  // Comparación correcta
{
    // Solo entra si voltaje es 400
}

Error 2: Olvidar paréntesis en expresiones mixtas

Síntoma: Resultado inesperado por precedencia.

bool ok = voltaje > 207 && voltaje < 253 || corriente < 16;
// ¿Qué se evalúa primero?

Solución: Usa paréntesis

bool ok = ((voltaje > 207) && (voltaje < 253)) || (corriente < 16);

Error 3: División entera cuando esperas decimal

Ya lo vimos en el capítulo anterior, pero es tan común que vale la pena repetirlo:

int total = 100;
int partes = 3;
double resultado = total / partes;  // 33.0, no 33.333...

Solución:

double resultado = (double)total / partes;  // 33.333...

Desafíos (Opcional)

Desafío 1: Selector de cable automático

Dificultad: Media

Crea un script que dados:

  • Corriente del circuito
  • Longitud del cable
  • Caída de tensión máxima permitida

Determine la sección mínima necesaria de cable y sugiera la sección normalizada más cercana (1.5, 2.5, 4, 6, 10, 16 mm²).

Pista

Usa la fórmula: S = (2 × L × I × ρ) / ΔV

Luego compara el resultado con cada sección normalizada hasta encontrar la primera que sea mayor o igual.


Desafío 2: Calculadora de corrección de factor de potencia

Dificultad: Alta

Crea un script que:

  • Reciba: potencia activa, factor de potencia actual, factor de potencia objetivo
  • Calcule: capacidad del banco de capacitores necesario (kVAr)
  • Valide: que el factor de potencia objetivo sea mayor que el actual

Fórmulas:

  • Qc = P × (tan(φ1) - tan(φ2))
  • donde φ = acos(factor de potencia)
Pista

Usa Math.Acos() para obtener el ángulo a partir del factor de potencia, y Math.Tan() para la tangente.


Desafío 3: Verificador de cortocircuito

Dificultad: Alta

Calcula la corriente de cortocircuito en el extremo de un cable y verifica si el poder de corte del interruptor es suficiente.

Datos:

  • Corriente de cortocircuito en el origen (Icc)
  • Impedancia del cable: Z = (ρ × L) / S
  • Icc en el extremo = V / Z_total

Valida que el interruptor tenga capacidad suficiente.


Recursos adicionales


Preguntas frecuentes

P: ¿Cuándo uso && y cuándo uso ||?

R: Usa && (AND) cuando todas las condiciones deben cumplirse. Usa || (OR) cuando al menos una debe cumplirse. Piensa: "Voltaje OK Y corriente OK" usa &&. "Voltaje fuera de rango O corriente excesiva" usa ||.

P: ¿Por qué a veces uso paréntesis en expresiones y a veces no?

R: Los paréntesis fuerzan el orden de evaluación y mejoran la legibilidad. Siempre úsalos cuando combines operadores diferentes (aritméticos con lógicos) o cuando tengas dudas sobre precedencia.

P: ¿Cuál es la diferencia entre i++ y ++i?

R: i++ (postfijo) devuelve el valor actual y luego incrementa. ++i (prefijo) incrementa primero y luego devuelve el nuevo valor. En la práctica, úsalos en líneas separadas y no habrá diferencia.

P: ¿Puedo comparar dos double con == ?

R: Técnicamente sí, pero no es recomendable por problemas de precisión de punto flotante. Es mejor comparar con una tolerancia: Math.Abs(a - b) < 0.0001.

P: ¿Qué pasa si divido por cero?

R: Con enteros, lanza una excepción (error). Con double, devuelve Infinity. Siempre valida que el divisor no sea cero antes de dividir.


Checklist de completitud

Antes de pasar al siguiente capítulo, asegúrate de:

  • Entender todos los operadores aritméticos (incluyendo % y ++)
  • Poder usar operadores de comparación para evaluar condiciones
  • Saber combinar condiciones con &&, ||, y !
  • Entender el orden de precedencia de operadores
  • Haber ejecutado exitosamente el script de verificación
  • Poder construir expresiones complejas para cálculos eléctricos
  • Saber dividir expresiones complejas en pasos más simples
  • (Opcional) Haber intentado al menos un desafío

Última actualización: Enero 2025 Tiempo de lectura estimado: 45-50 minutos Código de ejemplo: code/cap-04/