Número a texto (0-9999)
Convierte un número entero de hasta 4 cifras a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) y subprogramas para manejar las irregularidades reales del idioma (11-15, 16-29 fusionados, "cien" vs "ciento").
Abrir en el editor →Algoritmo de ejemplo, listo para ejecutar paso a paso en el navegador. Sin instalar nada.
Diagrama de flujo
Pseudocódigo
Algoritmo main
// Convierte un número entero entre 0 y 9999 a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) para las irregularidades reales del idioma (11-15, 16-29 fusionados, 'cien' vs 'ciento', decenas y centenas con nombre propio) en vez de intentar una fórmula puramente aritmética.
pal(1) <- "cero"
pal(2) <- "uno"
pal(3) <- "dos"
pal(4) <- "tres"
pal(5) <- "cuatro"
pal(6) <- "cinco"
pal(7) <- "seis"
pal(8) <- "siete"
pal(9) <- "ocho"
pal(10) <- "nueve"
pal(11) <- "diez"
pal(12) <- "once"
pal(13) <- "doce"
pal(14) <- "trece"
pal(15) <- "catorce"
pal(16) <- "quince"
pal(17) <- "dieciséis"
pal(18) <- "diecisiete"
pal(19) <- "dieciocho"
pal(20) <- "diecinueve"
pal(21) <- "veinte"
pal(22) <- "veintiuno"
pal(23) <- "veintidós"
pal(24) <- "veintitrés"
pal(25) <- "veinticuatro"
pal(26) <- "veinticinco"
pal(27) <- "veintiséis"
pal(28) <- "veintisiete"
pal(29) <- "veintiocho"
pal(30) <- "veintinueve"
dec(3) <- "treinta"
dec(4) <- "cuarenta"
dec(5) <- "cincuenta"
dec(6) <- "sesenta"
dec(7) <- "setenta"
dec(8) <- "ochenta"
dec(9) <- "noventa"
cen(2) <- "doscientos"
cen(3) <- "trescientos"
cen(4) <- "cuatrocientos"
cen(5) <- "quinientos"
cen(6) <- "seiscientos"
cen(7) <- "setecientos"
cen(8) <- "ochocientos"
cen(9) <- "novecientos"
Leer N
Si N==0
resultado <- "cero"
SiNo
miles <- TRUNC(N/1000)
resto <- N MOD 1000
resultado <- ""
Si miles>0
Si miles==1
resultado <- "mil"
SiNo
resultado <- pal(miles+1) + " mil"
FinSi
FinSi
Si resto>0
ConvertirMenorQueMil(resto, pal, dec, cen, palabraResto)
Si miles>0
resultado <- resultado + " " + palabraResto
SiNo
resultado <- palabraResto
FinSi
FinSi
FinSi
Escribir "El número ", N, " en palabras es: ", resultado
FinAlgoritmo
Funcion ConvertirMenorQueMil(n, pal, dec, cen, palabra)
// Convierte un número entre 0 y 999 a su palabra en español — maneja el caso irregular 'cien' (sin 'to') vs 'ciento' (con más dígitos detrás), y delega las decenas/unidades a ConvertirMenorQueCien.
c <- TRUNC(n/100)
r <- n MOD 100
palabra <- ""
Si c>0
Si c==1 Y r==0
palabra <- "cien"
SiNo
Si c==1
palabra <- "ciento"
SiNo
palabra <- cen(c)
FinSi
FinSi
FinSi
Si r>0
ConvertirMenorQueCien(r, pal, dec, palabraR)
Si c>0
palabra <- palabra + " " + palabraR
SiNo
palabra <- palabraR
FinSi
FinSi
FinFuncion
Funcion ConvertirMenorQueCien(n, pal, dec, palabra)
// Convierte un número entre 0 y 99 a su palabra en español, usando las tablas 'pal' (0-29, con las irregularidades de 11-15 y 16-29 fusionadas) y 'dec' (múltiplos de diez desde 30).
Si n<=29
palabra <- pal(n+1)
SiNo
d <- TRUNC(n/10)
u <- n MOD 10
palabra <- dec(d)
Si u>0
palabra <- palabra + " y " + pal(u+1)
FinSi
FinSi
FinFuncion
El mismo algoritmo en Java
package org.desarrollo;
import java.util.ArrayList;
import java.util.Scanner;
/**
* Proyecto Java generado por freeDFDWeb a partir de un diagrama DFD.
*/
public class FreeDFDMain {
/**
* Convierte un número entero entre 0 y 9999 a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) para las irregularidades reales del idioma (11-15, 16-29 fusionados, 'cien' vs 'ciento', decenas y centenas con nombre propio) en vez de intentar una fórmula puramente aritmética.
*
* @param args no utilizado — freeDFDWeb no pasa argumentos de línea de comandos.
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Double> pal = new ArrayList<>();
ArrayList<Double> dec = new ArrayList<>();
ArrayList<Double> cen = new ArrayList<>();
double N = 0.0;
String resultado = null;
double miles = 0.0;
double resto = 0.0;
double[] palabraResto = {0.0}; // Arreglo de 1 elemento: simula paso por referencia (Java no permite mutar un double pasado a otro método) — se usa como "palabraResto[0]" en el resto del método
vecSet(pal, (int)(1), "cero");
vecSet(pal, (int)(2), "uno");
vecSet(pal, (int)(3), "dos");
vecSet(pal, (int)(4), "tres");
vecSet(pal, (int)(5), "cuatro");
vecSet(pal, (int)(6), "cinco");
vecSet(pal, (int)(7), "seis");
vecSet(pal, (int)(8), "siete");
vecSet(pal, (int)(9), "ocho");
vecSet(pal, (int)(10), "nueve");
vecSet(pal, (int)(11), "diez");
vecSet(pal, (int)(12), "once");
vecSet(pal, (int)(13), "doce");
vecSet(pal, (int)(14), "trece");
vecSet(pal, (int)(15), "catorce");
vecSet(pal, (int)(16), "quince");
vecSet(pal, (int)(17), "dieciséis");
vecSet(pal, (int)(18), "diecisiete");
vecSet(pal, (int)(19), "dieciocho");
vecSet(pal, (int)(20), "diecinueve");
vecSet(pal, (int)(21), "veinte");
vecSet(pal, (int)(22), "veintiuno");
vecSet(pal, (int)(23), "veintidós");
vecSet(pal, (int)(24), "veintitrés");
vecSet(pal, (int)(25), "veinticuatro");
vecSet(pal, (int)(26), "veinticinco");
vecSet(pal, (int)(27), "veintiséis");
vecSet(pal, (int)(28), "veintisiete");
vecSet(pal, (int)(29), "veintiocho");
vecSet(pal, (int)(30), "veintinueve");
vecSet(dec, (int)(3), "treinta");
vecSet(dec, (int)(4), "cuarenta");
vecSet(dec, (int)(5), "cincuenta");
vecSet(dec, (int)(6), "sesenta");
vecSet(dec, (int)(7), "setenta");
vecSet(dec, (int)(8), "ochenta");
vecSet(dec, (int)(9), "noventa");
vecSet(cen, (int)(2), "doscientos");
vecSet(cen, (int)(3), "trescientos");
vecSet(cen, (int)(4), "cuatrocientos");
vecSet(cen, (int)(5), "quinientos");
vecSet(cen, (int)(6), "seiscientos");
vecSet(cen, (int)(7), "setecientos");
vecSet(cen, (int)(8), "ochocientos");
vecSet(cen, (int)(9), "novecientos");
N = readDouble(scanner);
if (((N == 0))) {
resultado = "cero";
} else {
miles = (double)(long)(div(N, 1000));
resto = mod(N, 1000);
resultado = "";
if (((miles > 0))) {
if (((miles == 1))) {
resultado = "mil";
} else {
resultado = (fmt(vecGet(pal, (int)((miles + 1)))) + " mil");
}
}
if (((resto > 0))) {
ConvertirMenorQueMil(resto, pal, dec, cen, palabraResto);
if (((miles > 0))) {
resultado = ((resultado + " ") + fmt(palabraResto[0]));
} else {
resultado = palabraResto[0];
}
}
}
System.out.println("El número " + fmt(N) + " en palabras es: " + resultado);
}
/**
* Convierte un número entre 0 y 999 a su palabra en español — maneja el caso irregular 'cien' (sin 'to') vs 'ciento' (con más dígitos detrás), y delega las decenas/unidades a ConvertirMenorQueCien.
*
* @param n double
* @param pal double
* @param dec double
* @param cen ArrayList<Double>
* @param palabra String[] — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
*/
static void ConvertirMenorQueMil(double n, double pal, double dec, ArrayList<Double> cen, String[] palabra) {
double c = 0.0;
double r = 0.0;
double[] palabraR = {0.0}; // Arreglo de 1 elemento: simula paso por referencia (Java no permite mutar un double pasado a otro método) — se usa como "palabraR[0]" en el resto del método
c = (double)(long)(div(n, 100));
r = mod(n, 100);
palabra[0] = "";
if (((c > 0))) {
if (((((c == 1)) && ((r == 0))))) {
palabra[0] = "cien";
} else {
if (((c == 1))) {
palabra[0] = "ciento";
} else {
palabra[0] = vecGet(cen, (int)(c));
}
}
}
if (((r > 0))) {
ConvertirMenorQueCien(r, pal, dec, palabraR);
if (((c > 0))) {
palabra[0] = ((palabra[0] + " ") + fmt(palabraR[0]));
} else {
palabra[0] = palabraR[0];
}
}
}
/**
* Convierte un número entre 0 y 99 a su palabra en español, usando las tablas 'pal' (0-29, con las irregularidades de 11-15 y 16-29 fusionadas) y 'dec' (múltiplos de diez desde 30).
*
* @param n double
* @param pal ArrayList<Double>
* @param dec ArrayList<Double>
* @param palabra double[] — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
*/
static void ConvertirMenorQueCien(double n, ArrayList<Double> pal, ArrayList<Double> dec, double[] palabra) {
double d = 0.0;
double u = 0.0;
if (((n <= 29))) {
palabra[0] = vecGet(pal, (int)((n + 1)));
} else {
d = (double)(long)(div(n, 10));
u = mod(n, 10);
palabra[0] = vecGet(dec, (int)(d));
if (((u > 0))) {
palabra[0] = ((fmt(palabra[0]) + " y ") + fmt(vecGet(pal, (int)((u + 1)))));
}
}
}
static boolean readBoolean(Scanner scanner) {
String t = scanner.nextLine().trim().toLowerCase();
if (t.equals("verdadero") || t.equals("true") || t.equals("1")) return true;
if (t.equals("falso") || t.equals("false") || t.equals("0")) return false;
throw new RuntimeException("Se esperaba Verdadero o Falso, se recibio: " + t);
}
static double readDouble(Scanner scanner) {
return Double.parseDouble(scanner.nextLine().trim());
}
static ArrayList<Double> readVector(Scanner scanner) {
ArrayList<Double> result = new ArrayList<>();
for (String token : scanner.nextLine().split(",")) {
String t = token.trim();
if (!t.isEmpty()) result.add(Double.parseDouble(t));
}
return result;
}
/** Formatea un double sin ".0" final cuando es entero — replica cómo freeDFDWeb (JS) imprime números, ej. factorial(5) debe mostrar "120", no "120.0". */
static String fmt(double d) {
if (!Double.isInfinite(d) && !Double.isNaN(d) && d == Math.floor(d) && Math.abs(d) < 1e15) {
return String.valueOf((long) d);
}
return String.valueOf(d);
}
/** `String.valueOf(true)` da "true" — el pseudolenguaje escribe e imprime "Verdadero"/"Falso". */
static String boolStr(boolean b) {
return b ? "Verdadero" : "Falso";
}
/** `ToChar(n)` de Flowgorithm: código de carácter → carácter. `Character.toChars` cubre también los puntos fuera del BMP (emoji), que no caben en un `char`. */
static String toChar(double code) {
int c = (int) code;
if (c < 0 || c > 0x10FFFF) {
throw new RuntimeException("ToChar(" + c + "): codigo de caracter fuera de rango");
}
return new String(Character.toChars(c));
}
/** `ToFixed(r, i)` de Flowgorithm: TRUNCA a `i` decimales, no redondea. `Locale.ROOT` para que el separador sea el punto siempre, igual que el resto del generador. */
static String toFixed(double value, double digits) {
int d = (int) digits;
double factor = Math.pow(10, d);
double truncated = (double)(long)(value * factor) / factor;
return String.format(java.util.Locale.ROOT, "%." + d + "f", truncated);
}
static double vecGet(ArrayList<Double> v, int index) {
int i = index - 1;
if (i < 0 || i >= v.size() || v.get(i) == null) {
throw new RuntimeException("La posición " + index + " del vector no tiene un valor asignado todavía");
}
return v.get(i);
}
static void vecSet(ArrayList<Double> v, int index, double value) {
int i = index - 1;
while (v.size() <= i) v.add(null);
v.set(i, value);
}
static double div(double a, double b) {
if (b == 0) throw new ArithmeticException("División por cero");
return a / b;
}
static double mod(double a, double b) {
if (b == 0) throw new ArithmeticException("Módulo por cero");
return a % b;
}
static void sleep(double seconds) {
try { Thread.sleep((long) (seconds * 1000)); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}
El mismo algoritmo en Python
#!/usr/bin/env python3
"""
Programa generado por freeDFDWeb — pseudocódigo exportado a Python.
Para correr: python3 main.py (ver README.md)
"""
import math
import random
import sys
import time
import datetime
class DfdRuntimeError(Exception):
pass
def read_boolean():
t = input().strip().lower()
if t in ('verdadero', 'true', '1'):
return True
if t in ('falso', 'false', '0'):
return False
raise DfdRuntimeError('Se esperaba Verdadero o Falso, se recibio: ' + t)
def read_double():
return float(input().strip())
def read_vector():
return [float(t.strip()) for t in input().split(',') if t.strip() != '']
def fmt(d):
"""Formatea sin ".0" final cuando es entero — replica cómo freeDFDWeb (JS) imprime números."""
if math.isinf(d):
return 'Infinity' if d > 0 else '-Infinity'
if math.isnan(d):
return 'NaN'
if d == math.floor(d) and abs(d) < 1e15:
return str(int(d))
return str(d)
def bool_str(b):
"""`str(True)` da "True" (mayúscula) — el pseudolenguaje escribe e imprime "Verdadero"/"Falso"."""
return 'Verdadero' if b else 'Falso'
def sgn(x):
"""`Sgn(n)` de Flowgorithm. Devuelve x tal cual en el cero para conservar el signo del -0.0, igual que `Math.sign` de JS."""
if math.isnan(x):
return x
if x > 0:
return 1.0
if x < 0:
return -1.0
return x
def to_fixed(value, digits):
"""`ToFixed(r, i)` de Flowgorithm: TRUNCA a i decimales, no redondea."""
d = int(digits)
factor = 10 ** d
truncated = math.trunc(value * factor) / factor
return f'{truncated:.{d}f}'
def vec_get(v, index):
i = index - 1
if i < 0 or i >= len(v) or v[i] is None:
raise DfdRuntimeError(f'La posición {index} del vector no tiene un valor asignado todavía')
return v[i]
def vec_set(v, index, value):
i = index - 1
while len(v) <= i:
v.append(None)
v[i] = value
def div(a, b):
if b == 0:
raise DfdRuntimeError('División por cero')
return a / b
def mod(a, b):
if b == 0:
raise DfdRuntimeError('Módulo por cero')
# `math.fmod`, NUNCA el `%` nativo de Python — el signo del resultado de
# `%` en Python sigue al DIVISOR (-7 % 3 == 2), mientras que JS (y el
# intérprete real) usan resto con signo del DIVIDENDO (-7 % 3 == -1),
# que es exactamente lo que `math.fmod` reproduce.
return math.fmod(a, b)
def redon(x):
"""Redondeo tipo `Math.round` de JS (.5 siempre hacia +Infinity) — NUNCA `round()` nativo de Python (redondeo bancario: round(2.5) == 2)."""
return math.floor(x + 0.5)
def ConvertirMenorQueMil(n, pal, dec, cen, palabra):
"""
Convierte un número entre 0 y 999 a su palabra en español — maneja el caso irregular 'cien' (sin 'to') vs 'ciento' (con más dígitos detrás), y delega las decenas/unidades a ConvertirMenorQueCien.
Args:
n: float
pal: float
dec: float
cen: list[float]
palabra: str — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
"""
palabraR = [0.0] # Lista de 1 elemento: simula paso por referencia (Python no permite mutar un float pasado a otra función) — se usa como "palabraR[0]" en el resto de la función
c = float(math.trunc(div(n, 100)))
r = mod(n, 100)
palabra[0] = ""
if (c > 0):
if ((c == 1) and (r == 0)):
palabra[0] = "cien"
else:
if (c == 1):
palabra[0] = "ciento"
else:
palabra[0] = vec_get(cen, int(c))
if (r > 0):
ConvertirMenorQueCien(r, pal, dec, palabraR)
if (c > 0):
palabra[0] = ((palabra[0] + " ") + fmt(palabraR[0]))
else:
palabra[0] = palabraR[0]
def ConvertirMenorQueCien(n, pal, dec, palabra):
"""
Convierte un número entre 0 y 99 a su palabra en español, usando las tablas 'pal' (0-29, con las irregularidades de 11-15 y 16-29 fusionadas) y 'dec' (múltiplos de diez desde 30).
Args:
n: float
pal: list[float]
dec: list[float]
palabra: float — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
"""
if (n <= 29):
palabra[0] = vec_get(pal, int((n + 1)))
else:
d = float(math.trunc(div(n, 10)))
u = mod(n, 10)
palabra[0] = vec_get(dec, int(d))
if (u > 0):
palabra[0] = ((fmt(palabra[0]) + " y ") + fmt(vec_get(pal, int((u + 1)))))
def main():
"""Convierte un número entero entre 0 y 9999 a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) para las irregularidades reales del idioma (11-15, 16-29 fusionados, 'cien' vs 'ciento', decenas y centenas con nombre propio) en vez de intentar una fórmula puramente aritmética."""
pal = []
dec = []
cen = []
palabraResto = [0.0] # Lista de 1 elemento: simula paso por referencia (Python no permite mutar un float pasado a otra función) — se usa como "palabraResto[0]" en el resto de la función
vec_set(pal, int(1), "cero")
vec_set(pal, int(2), "uno")
vec_set(pal, int(3), "dos")
vec_set(pal, int(4), "tres")
vec_set(pal, int(5), "cuatro")
vec_set(pal, int(6), "cinco")
vec_set(pal, int(7), "seis")
vec_set(pal, int(8), "siete")
vec_set(pal, int(9), "ocho")
vec_set(pal, int(10), "nueve")
vec_set(pal, int(11), "diez")
vec_set(pal, int(12), "once")
vec_set(pal, int(13), "doce")
vec_set(pal, int(14), "trece")
vec_set(pal, int(15), "catorce")
vec_set(pal, int(16), "quince")
vec_set(pal, int(17), "dieciséis")
vec_set(pal, int(18), "diecisiete")
vec_set(pal, int(19), "dieciocho")
vec_set(pal, int(20), "diecinueve")
vec_set(pal, int(21), "veinte")
vec_set(pal, int(22), "veintiuno")
vec_set(pal, int(23), "veintidós")
vec_set(pal, int(24), "veintitrés")
vec_set(pal, int(25), "veinticuatro")
vec_set(pal, int(26), "veinticinco")
vec_set(pal, int(27), "veintiséis")
vec_set(pal, int(28), "veintisiete")
vec_set(pal, int(29), "veintiocho")
vec_set(pal, int(30), "veintinueve")
vec_set(dec, int(3), "treinta")
vec_set(dec, int(4), "cuarenta")
vec_set(dec, int(5), "cincuenta")
vec_set(dec, int(6), "sesenta")
vec_set(dec, int(7), "setenta")
vec_set(dec, int(8), "ochenta")
vec_set(dec, int(9), "noventa")
vec_set(cen, int(2), "doscientos")
vec_set(cen, int(3), "trescientos")
vec_set(cen, int(4), "cuatrocientos")
vec_set(cen, int(5), "quinientos")
vec_set(cen, int(6), "seiscientos")
vec_set(cen, int(7), "setecientos")
vec_set(cen, int(8), "ochocientos")
vec_set(cen, int(9), "novecientos")
N = read_double()
if (N == 0):
resultado = "cero"
else:
miles = float(math.trunc(div(N, 1000)))
resto = mod(N, 1000)
resultado = ""
if (miles > 0):
if (miles == 1):
resultado = "mil"
else:
resultado = (fmt(vec_get(pal, int((miles + 1)))) + " mil")
if (resto > 0):
ConvertirMenorQueMil(resto, pal, dec, cen, palabraResto)
if (miles > 0):
resultado = ((resultado + " ") + fmt(palabraResto[0]))
else:
resultado = palabraResto[0]
print("El número " + fmt(N) + " en palabras es: " + resultado)
if __name__ == '__main__':
main()
El mismo algoritmo en C#
using System;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Excepción propia para errores de ejecución del programa generado (división por cero, índice de vector sin asignar, etc.) — mismo criterio que el `RuntimeError` real de freeDFDWeb.</summary>
class DfdRuntimeException : Exception {
public DfdRuntimeException(string message) : base(message) { }
}
/// <summary>
/// Proyecto C# generado por freeDFDWeb a partir de un diagrama DFD.
/// </summary>
class Program {
/// <summary>
/// Convierte un número entero entre 0 y 9999 a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) para las irregularidades reales del idioma (11-15, 16-29 fusionados, 'cien' vs 'ciento', decenas y centenas con nombre propio) en vez de intentar una fórmula puramente aritmética.
/// </summary>
/// <param name="args">no utilizado — freeDFDWeb no pasa argumentos de línea de comandos.</param>
static void Main(string[] args) {
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
List<double?> pal = new List<double?>();
List<double?> dec = new List<double?>();
List<double?> cen = new List<double?>();
double N = 0.0;
string resultado = null;
double miles = 0.0;
double resto = 0.0;
double palabraResto = 0.0;
VecSet(pal, (int)(1), "cero");
VecSet(pal, (int)(2), "uno");
VecSet(pal, (int)(3), "dos");
VecSet(pal, (int)(4), "tres");
VecSet(pal, (int)(5), "cuatro");
VecSet(pal, (int)(6), "cinco");
VecSet(pal, (int)(7), "seis");
VecSet(pal, (int)(8), "siete");
VecSet(pal, (int)(9), "ocho");
VecSet(pal, (int)(10), "nueve");
VecSet(pal, (int)(11), "diez");
VecSet(pal, (int)(12), "once");
VecSet(pal, (int)(13), "doce");
VecSet(pal, (int)(14), "trece");
VecSet(pal, (int)(15), "catorce");
VecSet(pal, (int)(16), "quince");
VecSet(pal, (int)(17), "dieciséis");
VecSet(pal, (int)(18), "diecisiete");
VecSet(pal, (int)(19), "dieciocho");
VecSet(pal, (int)(20), "diecinueve");
VecSet(pal, (int)(21), "veinte");
VecSet(pal, (int)(22), "veintiuno");
VecSet(pal, (int)(23), "veintidós");
VecSet(pal, (int)(24), "veintitrés");
VecSet(pal, (int)(25), "veinticuatro");
VecSet(pal, (int)(26), "veinticinco");
VecSet(pal, (int)(27), "veintiséis");
VecSet(pal, (int)(28), "veintisiete");
VecSet(pal, (int)(29), "veintiocho");
VecSet(pal, (int)(30), "veintinueve");
VecSet(dec, (int)(3), "treinta");
VecSet(dec, (int)(4), "cuarenta");
VecSet(dec, (int)(5), "cincuenta");
VecSet(dec, (int)(6), "sesenta");
VecSet(dec, (int)(7), "setenta");
VecSet(dec, (int)(8), "ochenta");
VecSet(dec, (int)(9), "noventa");
VecSet(cen, (int)(2), "doscientos");
VecSet(cen, (int)(3), "trescientos");
VecSet(cen, (int)(4), "cuatrocientos");
VecSet(cen, (int)(5), "quinientos");
VecSet(cen, (int)(6), "seiscientos");
VecSet(cen, (int)(7), "setecientos");
VecSet(cen, (int)(8), "ochocientos");
VecSet(cen, (int)(9), "novecientos");
N = ReadDouble();
if ((N == 0)) {
resultado = "cero";
} else {
miles = Math.Truncate(Div(N, 1000));
resto = Mod(N, 1000);
resultado = "";
if ((miles > 0)) {
if ((miles == 1)) {
resultado = "mil";
} else {
resultado = (Fmt(VecGet(pal, (int)((miles + 1)))) + " mil");
}
}
if ((resto > 0)) {
ConvertirMenorQueMil(resto, pal, dec, cen, ref palabraResto);
if ((miles > 0)) {
resultado = ((resultado + " ") + Fmt(palabraResto));
} else {
resultado = palabraResto;
}
}
}
Console.WriteLine("El número " + Fmt(N) + " en palabras es: " + resultado);
}
/// <summary>
/// Convierte un número entre 0 y 999 a su palabra en español — maneja el caso irregular 'cien' (sin 'to') vs 'ciento' (con más dígitos detrás), y delega las decenas/unidades a ConvertirMenorQueCien.
/// </summary>
/// <param name="n">double</param>
/// <param name="pal">double</param>
/// <param name="dec">double</param>
/// <param name="cen">List<double?></param>
/// <param name="palabra">string — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)</param>
static void ConvertirMenorQueMil(double n, double pal, double dec, List<double?> cen, ref string palabra) {
double c = 0.0;
double r = 0.0;
double palabraR = 0.0;
c = Math.Truncate(Div(n, 100));
r = Mod(n, 100);
palabra = "";
if ((c > 0)) {
if (((c == 1) && (r == 0))) {
palabra = "cien";
} else {
if ((c == 1)) {
palabra = "ciento";
} else {
palabra = VecGet(cen, (int)(c));
}
}
}
if ((r > 0)) {
ConvertirMenorQueCien(r, pal, dec, ref palabraR);
if ((c > 0)) {
palabra = ((palabra + " ") + Fmt(palabraR));
} else {
palabra = palabraR;
}
}
}
/// <summary>
/// Convierte un número entre 0 y 99 a su palabra en español, usando las tablas 'pal' (0-29, con las irregularidades de 11-15 y 16-29 fusionadas) y 'dec' (múltiplos de diez desde 30).
/// </summary>
/// <param name="n">double</param>
/// <param name="pal">List<double?></param>
/// <param name="dec">List<double?></param>
/// <param name="palabra">double — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)</param>
static void ConvertirMenorQueCien(double n, List<double?> pal, List<double?> dec, ref double palabra) {
double d = 0.0;
double u = 0.0;
if ((n <= 29)) {
palabra = VecGet(pal, (int)((n + 1)));
} else {
d = Math.Truncate(Div(n, 10));
u = Mod(n, 10);
palabra = VecGet(dec, (int)(d));
if ((u > 0)) {
palabra = ((Fmt(palabra) + " y ") + Fmt(VecGet(pal, (int)((u + 1)))));
}
}
}
static readonly Random Rnd = new Random();
static bool ReadBoolean() {
string t = (Console.ReadLine() ?? "").Trim().ToLowerInvariant();
if (t == "verdadero" || t == "true" || t == "1") return true;
if (t == "falso" || t == "false" || t == "0") return false;
throw new Exception("Se esperaba Verdadero o Falso, se recibio: " + t);
}
static double ReadDouble() {
return double.Parse(Console.ReadLine().Trim(), CultureInfo.InvariantCulture);
}
static List<double?> ReadVector() {
List<double?> result = new List<double?>();
foreach (string token in Console.ReadLine().Split(',')) {
string t = token.Trim();
if (t.Length > 0) result.Add(double.Parse(t, CultureInfo.InvariantCulture));
}
return result;
}
/// <summary>Formatea un double sin ".0" final cuando es entero — replica cómo freeDFDWeb (JS) imprime números.</summary>
static string Fmt(double d) {
if (double.IsPositiveInfinity(d)) return "Infinity";
if (double.IsNegativeInfinity(d)) return "-Infinity";
if (double.IsNaN(d)) return "NaN";
if (d == Math.Floor(d) && Math.Abs(d) < 1e15) {
return ((long)d).ToString(CultureInfo.InvariantCulture);
}
return d.ToString(CultureInfo.InvariantCulture);
}
/// <summary>`true.ToString()` da "True" (mayúscula) — el pseudolenguaje escribe e imprime "Verdadero"/"Falso".</summary>
static string BoolStr(bool b) {
return b ? "Verdadero" : "Falso";
}
/// <summary>`Sgn(n)` de Flowgorithm. Helper y no `Math.Sign`: ese LANZA sobre NaN, mientras el intérprete devuelve NaN. Devuelve x en el cero para conservar el -0.0.</summary>
static double Sgn(double x) {
if (double.IsNaN(x)) return x;
if (x > 0) return 1.0;
if (x < 0) return -1.0;
return x;
}
/// <summary>`ToFixed(r, i)` de Flowgorithm: TRUNCA a i decimales, no redondea. `InvariantCulture` para que el separador sea el punto, igual que `Fmt`.</summary>
static string ToFixed(double value, double digits) {
int d = (int) digits;
double factor = Math.Pow(10, d);
double truncated = Math.Truncate(value * factor) / factor;
return truncated.ToString("F" + d, CultureInfo.InvariantCulture);
}
static double VecGet(List<double?> v, int index) {
int i = index - 1;
if (i < 0 || i >= v.Count || !v[i].HasValue) {
throw new DfdRuntimeException("La posición " + index + " del vector no tiene un valor asignado todavía");
}
return v[i].Value;
}
static void VecSet(List<double?> v, int index, double value) {
int i = index - 1;
while (v.Count <= i) v.Add(null);
v[i] = value;
}
static double Div(double a, double b) {
if (b == 0) throw new DfdRuntimeException("División por cero");
return a / b;
}
static double Mod(double a, double b) {
if (b == 0) throw new DfdRuntimeException("Módulo por cero");
// El operador `%` nativo de C# para `double` SÍ coincide con el
// signo de JS (confirmado real: -7 % 3 == -1 en ambos) — a
// diferencia de Python, no hace falta ningún wrapper de signo.
return a % b;
}
/// <summary>Redondeo tipo `Math.round` de JS (.5 siempre hacia +Infinity) — NUNCA `Math.Round()` directo (bancario en .NET: Math.Round(2.5) == 2).</summary>
static double Redon(double x) {
return Math.Floor(x + 0.5);
}
}
El mismo algoritmo en C++
#include <iostream>
#include <string>
#include <vector>
#include <optional>
#include <cmath>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <thread>
#include <charconv>
#include <stdexcept>
/**
* Programa C++ generado por freeDFDWeb a partir de un diagrama DFD.
*/
const double PI = 3.14159265358979323846;
class DfdRuntimeError : public std::runtime_error {
public:
explicit DfdRuntimeError(const std::string& message) : std::runtime_error(message) {}
};
std::string readLine() {
std::string line;
if (!std::getline(std::cin, line)) return "";
if (!line.empty() && line.back() == '\r') line.pop_back();
return line;
}
/** `std::stod` (usado por `toNumberOrThrow`) NO tira con texto no numérico de forma consistente en todos los casos (ignora sufijos raros) pero SÍ tira `std::invalid_argument` con texto totalmente no numérico — verificado real. Envuelto para relanzar como `DfdRuntimeError`, mismo tipo de excepción que el resto del programa generado. */
double toNumberOrThrow(const std::string& value) {
try {
return std::stod(value);
} catch (const std::exception&) {
throw DfdRuntimeError("Se esperaba un número, se encontró \"" + value + "\"");
}
}
bool readBoolean() {
std::string t = readLine();
for (auto& c : t) c = (char)std::tolower((unsigned char)c);
if (t == "verdadero" || t == "true" || t == "1") return true;
if (t == "falso" || t == "false" || t == "0") return false;
throw std::runtime_error("Se esperaba Verdadero o Falso, se recibio: " + t);
}
double readDouble() {
return toNumberOrThrow(readLine());
}
std::vector<std::optional<double>> readVector() {
std::vector<std::optional<double>> result;
std::stringstream ss(readLine());
std::string token;
while (std::getline(ss, token, ',')) {
size_t start = token.find_first_not_of(" \t");
size_t end = token.find_last_not_of(" \t");
if (start == std::string::npos) continue;
result.push_back(toNumberOrThrow(token.substr(start, end - start + 1)));
}
return result;
}
/** Formatea sin ".0" final cuando es entero, con representación de ida y vuelta exacta para decimales (`std::to_chars`, C++17) — replica cómo freeDFDWeb (JS) imprime números. Diverge de JS solo en notación científica de magnitudes extremas (ver comentario de cabecera del archivo), gap aceptado. */
std::string fmt(double d) {
if (std::isinf(d)) return d > 0 ? "Infinity" : "-Infinity";
if (std::isnan(d)) return "NaN";
char buf[64];
if (d == std::floor(d) && std::abs(d) < 1e15) {
auto res = std::to_chars(buf, buf + sizeof(buf), (long long)d);
return std::string(buf, res.ptr);
}
auto res = std::to_chars(buf, buf + sizeof(buf), d);
return std::string(buf, res.ptr);
}
/** `std::cout << bool` imprime "1"/"0" — el pseudolenguaje escribe e imprime "Verdadero"/"Falso". */
std::string boolStr(bool b) {
return b ? "Verdadero" : "Falso";
}
/** `Sgn(n)` de Flowgorithm. Devuelve x en el cero para conservar el signo del -0.0, igual que `Math.sign` de JS. */
double sgn(double x) {
if (std::isnan(x)) return x;
if (x > 0) return 1.0;
if (x < 0) return -1.0;
return x;
}
/** `ToChar(n)`: punto de código → carácter. C++ es el único destino sin conversión nativa, así que codifica UTF-8 a mano — `std::string` acá son bytes, no puntos de código. */
std::string toCharStr(double code) {
long long c = (long long) code;
if (c < 0 || c > 0x10FFFF) {
throw DfdRuntimeError("ToChar(" + std::to_string(c) + "): codigo de caracter fuera de rango");
}
std::string out;
if (c < 0x80) {
out += (char)c;
} else if (c < 0x800) {
out += (char)(0xC0 | (c >> 6));
out += (char)(0x80 | (c & 0x3F));
} else if (c < 0x10000) {
out += (char)(0xE0 | (c >> 12));
out += (char)(0x80 | ((c >> 6) & 0x3F));
out += (char)(0x80 | (c & 0x3F));
} else {
out += (char)(0xF0 | (c >> 18));
out += (char)(0x80 | ((c >> 12) & 0x3F));
out += (char)(0x80 | ((c >> 6) & 0x3F));
out += (char)(0x80 | (c & 0x3F));
}
return out;
}
/** `ToCode(c)`: inversa de `toCharStr` — decodifica el PRIMER punto de código UTF-8, no el primer byte (si no, una "ñ" daría 195). */
double toCode(const std::string& s) {
if (s.empty()) {
throw DfdRuntimeError("ToCode espera un texto de un caracter");
}
unsigned char b0 = (unsigned char)s[0];
if (b0 < 0x80) return (double)b0;
int extra = (b0 >= 0xF0) ? 3 : (b0 >= 0xE0) ? 2 : 1;
long long cp = b0 & (0x3F >> extra);
for (int i = 1; i <= extra; i++) {
if ((size_t)i >= s.size()) {
throw DfdRuntimeError("ToCode: texto UTF-8 mal formado");
}
cp = (cp << 6) | ((unsigned char)s[i] & 0x3F);
}
return (double)cp;
}
/** `ToFixed(r, i)` de Flowgorithm: TRUNCA a i decimales, no redondea. */
std::string toFixed(double value, double digits) {
int d = (int) digits;
double factor = std::pow(10.0, d);
double truncated = std::trunc(value * factor) / factor;
std::ostringstream out;
out << std::fixed << std::setprecision(d) << truncated;
return out.str();
}
std::string toUpperStr(const std::string& s) {
std::string result = s;
std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::toupper(c); });
return result;
}
std::string toLowerStr(const std::string& s) {
std::string result = s;
std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::tolower(c); });
return result;
}
double vecGet(std::vector<std::optional<double>>& v, int index) {
int i = index - 1;
if (i < 0 || (size_t)i >= v.size() || !v[i].has_value()) {
throw DfdRuntimeError("La posición " + std::to_string(index) + " del vector no tiene un valor asignado todavía");
}
return *v[i];
}
void vecSet(std::vector<std::optional<double>>& v, int index, double value) {
int i = index - 1;
if ((size_t)(i + 1) > v.size()) v.resize(i + 1);
v[i] = value;
}
/**
* `dividir` y no `div`, que sería el nombre obvio: `div` YA EXISTE en la
* biblioteca estándar de C (`<cstdlib>`, devuelve un `div_t`) y está
* declarada aunque no se incluya ese encabezado. Con dos literales
* enteros, `div(7, 2)` resuelve a la versión de C —coincidencia exacta—
* y el programa generado NO COMPILA:
*
* error: cannot convert 'div_t' to 'double'
*
* O sea: CUALQUIER programa con una división fallaba al exportar a C++.
* Encontrado el 30-oct-2026 compilando de verdad lo exportado
* (`scripts/equivalencia/comparar.mjs`); ninguna prueba lo veía porque
* ninguna compilaba C++.
*/
double dividir(double a, double b) {
if (b == 0) throw DfdRuntimeError("División por cero");
return a / b;
}
double mod(double a, double b) {
if (b == 0) throw DfdRuntimeError("Módulo por cero");
// `%` NO COMPILA sobre `double` en C++ — `std::fmod` es la única forma.
// Su signo SÍ coincide con JS (confirmado real), a diferencia de
// Python, que necesitaba un wrapper de signo además del de cero.
return std::fmod(a, b);
}
/** Redondeo tipo `Math.round` de JS (.5 siempre hacia +Infinity) — NUNCA `std::round()` directo (redondea siempre alejándose de cero: round(-2.5) == -3, distinto de Math.round(-2.5) == -2). */
double redon(double x) {
return std::floor(x + 0.5);
}
// ---------------------------------------------------------------------------
// Programa
// ---------------------------------------------------------------------------
/**
* Convierte un número entre 0 y 999 a su palabra en español — maneja el caso irregular 'cien' (sin 'to') vs 'ciento' (con más dígitos detrás), y delega las decenas/unidades a ConvertirMenorQueCien.
* @param n double
* @param pal double
* @param dec double
* @param cen std::vector<std::optional<double>>
* @param palabra std::string — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
*/
void ConvertirMenorQueMil(double n, double pal, double dec, std::vector<std::optional<double>> cen, std::string& palabra) {
double c = 0.0;
double r = 0.0;
double palabraR = 0.0;
c = std::trunc(dividir(n, 100));
r = mod(n, 100);
palabra = std::string("");
if ((c > 0)) {
if (((c == 1) && (r == 0))) {
palabra = std::string("cien");
} else {
if ((c == 1)) {
palabra = std::string("ciento");
} else {
palabra = vecGet(cen, (int)(c));
}
}
}
if ((r > 0)) {
ConvertirMenorQueCien(r, pal, dec, palabraR);
if ((c > 0)) {
palabra = ((palabra + std::string(" ")) + fmt(palabraR));
} else {
palabra = palabraR;
}
}
}
/**
* Convierte un número entre 0 y 99 a su palabra en español, usando las tablas 'pal' (0-29, con las irregularidades de 11-15 y 16-29 fusionadas) y 'dec' (múltiplos de diez desde 30).
* @param n double
* @param pal std::vector<std::optional<double>>
* @param dec std::vector<std::optional<double>>
* @param palabra double — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
*/
void ConvertirMenorQueCien(double n, std::vector<std::optional<double>> pal, std::vector<std::optional<double>> dec, double& palabra) {
double d = 0.0;
double u = 0.0;
if ((n <= 29)) {
palabra = vecGet(pal, (int)((n + 1)));
} else {
d = std::trunc(dividir(n, 10));
u = mod(n, 10);
palabra = vecGet(dec, (int)(d));
if ((u > 0)) {
palabra = ((fmt(palabra) + std::string(" y ")) + fmt(vecGet(pal, (int)((u + 1)))));
}
}
}
/**
* Convierte un número entero entre 0 y 9999 a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) para las irregularidades reales del idioma (11-15, 16-29 fusionados, 'cien' vs 'ciento', decenas y centenas con nombre propio) en vez de intentar una fórmula puramente aritmética.
*/
int main() {
std::vector<std::optional<double>> pal;
std::vector<std::optional<double>> dec;
std::vector<std::optional<double>> cen;
double N = 0.0;
std::string resultado = "";
double miles = 0.0;
double resto = 0.0;
double palabraResto = 0.0;
vecSet(pal, (int)(1), std::string("cero"));
vecSet(pal, (int)(2), std::string("uno"));
vecSet(pal, (int)(3), std::string("dos"));
vecSet(pal, (int)(4), std::string("tres"));
vecSet(pal, (int)(5), std::string("cuatro"));
vecSet(pal, (int)(6), std::string("cinco"));
vecSet(pal, (int)(7), std::string("seis"));
vecSet(pal, (int)(8), std::string("siete"));
vecSet(pal, (int)(9), std::string("ocho"));
vecSet(pal, (int)(10), std::string("nueve"));
vecSet(pal, (int)(11), std::string("diez"));
vecSet(pal, (int)(12), std::string("once"));
vecSet(pal, (int)(13), std::string("doce"));
vecSet(pal, (int)(14), std::string("trece"));
vecSet(pal, (int)(15), std::string("catorce"));
vecSet(pal, (int)(16), std::string("quince"));
vecSet(pal, (int)(17), std::string("dieciséis"));
vecSet(pal, (int)(18), std::string("diecisiete"));
vecSet(pal, (int)(19), std::string("dieciocho"));
vecSet(pal, (int)(20), std::string("diecinueve"));
vecSet(pal, (int)(21), std::string("veinte"));
vecSet(pal, (int)(22), std::string("veintiuno"));
vecSet(pal, (int)(23), std::string("veintidós"));
vecSet(pal, (int)(24), std::string("veintitrés"));
vecSet(pal, (int)(25), std::string("veinticuatro"));
vecSet(pal, (int)(26), std::string("veinticinco"));
vecSet(pal, (int)(27), std::string("veintiséis"));
vecSet(pal, (int)(28), std::string("veintisiete"));
vecSet(pal, (int)(29), std::string("veintiocho"));
vecSet(pal, (int)(30), std::string("veintinueve"));
vecSet(dec, (int)(3), std::string("treinta"));
vecSet(dec, (int)(4), std::string("cuarenta"));
vecSet(dec, (int)(5), std::string("cincuenta"));
vecSet(dec, (int)(6), std::string("sesenta"));
vecSet(dec, (int)(7), std::string("setenta"));
vecSet(dec, (int)(8), std::string("ochenta"));
vecSet(dec, (int)(9), std::string("noventa"));
vecSet(cen, (int)(2), std::string("doscientos"));
vecSet(cen, (int)(3), std::string("trescientos"));
vecSet(cen, (int)(4), std::string("cuatrocientos"));
vecSet(cen, (int)(5), std::string("quinientos"));
vecSet(cen, (int)(6), std::string("seiscientos"));
vecSet(cen, (int)(7), std::string("setecientos"));
vecSet(cen, (int)(8), std::string("ochocientos"));
vecSet(cen, (int)(9), std::string("novecientos"));
N = readDouble();
if ((N == 0)) {
resultado = std::string("cero");
} else {
miles = std::trunc(dividir(N, 1000));
resto = mod(N, 1000);
resultado = std::string("");
if ((miles > 0)) {
if ((miles == 1)) {
resultado = std::string("mil");
} else {
resultado = (fmt(vecGet(pal, (int)((miles + 1)))) + std::string(" mil"));
}
}
if ((resto > 0)) {
ConvertirMenorQueMil(resto, pal, dec, cen, palabraResto);
if ((miles > 0)) {
resultado = ((resultado + std::string(" ")) + fmt(palabraResto));
} else {
resultado = palabraResto;
}
}
}
std::cout << std::string("El número ") + fmt(N) + std::string(" en palabras es: ") + resultado << "\n";
return 0;
}
El mismo algoritmo en TypeScript
import * as fs from 'fs';
/**
* Generado por freeDFDWeb, sin descripción en el diagrama original.
*/
class DfdRuntimeError extends Error {}
const inputLines: string[] = fs.readFileSync(0, 'utf-8').split('\n');
let inputIndex = 0;
/** Toda la entrada se lee de una sola vez al arrancar (ver cabecera del archivo) — cada llamada consume la siguiente línea ya bufferizada. */
function readLine(): string {
return (inputLines[inputIndex++] ?? '').replace(/\r$/, '');
}
function readBoolean(): boolean {
const t = readLine().trim().toLowerCase();
if (t === 'verdadero' || t === 'true' || t === '1') return true;
if (t === 'falso' || t === 'false' || t === '0') return false;
throw new Error('Se esperaba Verdadero o Falso, se recibio: ' + t);
}
function readDouble(): number {
return toNumberOrThrow(readLine().trim());
}
function readVector(): (number | undefined)[] {
return readLine()
.split(',')
.map((t) => t.trim())
.filter((t) => t.length > 0)
.map((t) => toNumberOrThrow(t));
}
/** `Number(x)` nativo no tira error con texto no numérico (da `NaN`) — a diferencia del intérprete real (`toNumber`), que sí tira. Único punto donde este generador necesita reproducir ese comportamiento a mano. */
function toNumberOrThrow(value: string | number): number {
const n = Number(value);
if (Number.isNaN(n)) {
throw new DfdRuntimeError(`Se esperaba un número, se encontró "${value}"`);
}
return n;
}
/** `String(true)` da "true" — el pseudolenguaje escribe e imprime "Verdadero"/"Falso". */
function boolStr(b: boolean): string {
return b ? 'Verdadero' : 'Falso';
}
/** `ToFixed(r, i)` de Flowgorithm: TRUNCA a i decimales, no redondea — por eso no basta el `.toFixed()` nativo, que redondea. */
function toFixed(value: number, digits: number): string {
const d = Math.trunc(digits);
const factor = Math.pow(10, d);
return (Math.trunc(value * factor) / factor).toFixed(d);
}
function vecGet(v: (number | undefined)[], index: number): number {
const i = Math.trunc(index) - 1;
const value = v[i];
if (i < 0 || value === undefined) {
throw new DfdRuntimeError(`La posición ${index} del vector no tiene un valor asignado todavía`);
}
return value;
}
function vecSet(v: (number | undefined)[], index: number, value: number): void {
v[Math.trunc(index) - 1] = value;
}
function div(a: number, b: number): number {
if (b === 0) throw new DfdRuntimeError('División por cero');
return a / b;
}
function mod(a: number, b: number): number {
if (b === 0) throw new DfdRuntimeError('Módulo por cero');
// El `%` nativo de JS/TS coincide exacto con el del intérprete real
// (mismo motor) — a diferencia de Python, no hace falta ningún wrapper
// de signo, solo el chequeo de división por cero.
return a % b;
}
/**
* Convierte un número entre 0 y 999 a su palabra en español — maneja el caso irregular 'cien' (sin 'to') vs 'ciento' (con más dígitos detrás), y delega las decenas/unidades a ConvertirMenorQueCien.
* @param n number
* @param pal number
* @param dec number
* @param cen (number | undefined)[]
* @param palabra string[] — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
*/
function ConvertirMenorQueMil(n: number, pal: number, dec: number, cen: (number | undefined)[], palabra: string[]): void {
let c: number = 0;
let r: number = 0;
let palabraR: number[] = [0]; // Arreglo de 1 elemento: simula paso por referencia (JS/TS no tiene parámetros por referencia para primitivos) — se usa como "palabraR[0]" en el resto de la función
c = Math.trunc(div(n, 100));
r = mod(n, 100);
palabra[0] = "";
if ((c > 0)) {
if (((c === 1) && (r === 0))) {
palabra[0] = "cien";
} else {
if ((c === 1)) {
palabra[0] = "ciento";
} else {
palabra[0] = vecGet(cen, c);
}
}
}
if ((r > 0)) {
ConvertirMenorQueCien(r, pal, dec, palabraR);
if ((c > 0)) {
palabra[0] = ((palabra[0] + " ") + String(palabraR[0]));
} else {
palabra[0] = palabraR[0];
}
}
}
/**
* Convierte un número entre 0 y 99 a su palabra en español, usando las tablas 'pal' (0-29, con las irregularidades de 11-15 y 16-29 fusionadas) y 'dec' (múltiplos de diez desde 30).
* @param n number
* @param pal (number | undefined)[]
* @param dec (number | undefined)[]
* @param palabra number[] — por referencia (el subprograma lo reasigna; el valor final es visible para quien llama)
*/
function ConvertirMenorQueCien(n: number, pal: (number | undefined)[], dec: (number | undefined)[], palabra: number[]): void {
let d: number = 0;
let u: number = 0;
if ((n <= 29)) {
palabra[0] = vecGet(pal, (n + 1));
} else {
d = Math.trunc(div(n, 10));
u = mod(n, 10);
palabra[0] = vecGet(dec, d);
if ((u > 0)) {
palabra[0] = ((String(palabra[0]) + " y ") + String(vecGet(pal, (u + 1))));
}
}
}
/**
* Convierte un número entero entre 0 y 9999 a su forma escrita en palabras (español) — ej. 5432 -> "cinco mil cuatrocientos treinta y dos". Usa tablas (vectores) para las irregularidades reales del idioma (11-15, 16-29 fusionados, 'cien' vs 'ciento', decenas y centenas con nombre propio) en vez de intentar una fórmula puramente aritmética.
*/
function main(): void {
let pal: (number | undefined)[] = [];
let dec: (number | undefined)[] = [];
let cen: (number | undefined)[] = [];
let N: number = 0;
let resultado: string = '';
let miles: number = 0;
let resto: number = 0;
let palabraResto: number[] = [0]; // Arreglo de 1 elemento: simula paso por referencia (JS/TS no tiene parámetros por referencia para primitivos) — se usa como "palabraResto[0]" en el resto de la función
vecSet(pal, 1, "cero");
vecSet(pal, 2, "uno");
vecSet(pal, 3, "dos");
vecSet(pal, 4, "tres");
vecSet(pal, 5, "cuatro");
vecSet(pal, 6, "cinco");
vecSet(pal, 7, "seis");
vecSet(pal, 8, "siete");
vecSet(pal, 9, "ocho");
vecSet(pal, 10, "nueve");
vecSet(pal, 11, "diez");
vecSet(pal, 12, "once");
vecSet(pal, 13, "doce");
vecSet(pal, 14, "trece");
vecSet(pal, 15, "catorce");
vecSet(pal, 16, "quince");
vecSet(pal, 17, "dieciséis");
vecSet(pal, 18, "diecisiete");
vecSet(pal, 19, "dieciocho");
vecSet(pal, 20, "diecinueve");
vecSet(pal, 21, "veinte");
vecSet(pal, 22, "veintiuno");
vecSet(pal, 23, "veintidós");
vecSet(pal, 24, "veintitrés");
vecSet(pal, 25, "veinticuatro");
vecSet(pal, 26, "veinticinco");
vecSet(pal, 27, "veintiséis");
vecSet(pal, 28, "veintisiete");
vecSet(pal, 29, "veintiocho");
vecSet(pal, 30, "veintinueve");
vecSet(dec, 3, "treinta");
vecSet(dec, 4, "cuarenta");
vecSet(dec, 5, "cincuenta");
vecSet(dec, 6, "sesenta");
vecSet(dec, 7, "setenta");
vecSet(dec, 8, "ochenta");
vecSet(dec, 9, "noventa");
vecSet(cen, 2, "doscientos");
vecSet(cen, 3, "trescientos");
vecSet(cen, 4, "cuatrocientos");
vecSet(cen, 5, "quinientos");
vecSet(cen, 6, "seiscientos");
vecSet(cen, 7, "setecientos");
vecSet(cen, 8, "ochocientos");
vecSet(cen, 9, "novecientos");
N = readDouble();
if ((N === 0)) {
resultado = "cero";
} else {
miles = Math.trunc(div(N, 1000));
resto = mod(N, 1000);
resultado = "";
if ((miles > 0)) {
if ((miles === 1)) {
resultado = "mil";
} else {
resultado = (String(vecGet(pal, (miles + 1))) + " mil");
}
}
if ((resto > 0)) {
ConvertirMenorQueMil(resto, pal, dec, cen, palabraResto);
if ((miles > 0)) {
resultado = ((resultado + " ") + String(palabraResto[0]));
} else {
resultado = palabraResto[0];
}
}
}
console.log("El número " + String(N) + " en palabras es: " + resultado);
}
main();
Generado por freeDFDWeb desde el diagrama de arriba. Es el mismo archivo que descarga el botón Exportar del editor.
Abre y guarda en los formatos que ya usas
Importa y exporta PSeInt (.psc) y Flowgorithm (.fprg), y abre archivos .dfd del DFD clásico. Todo en el navegador, sin instalar nada: sirve en Windows, Mac, Linux, Chromebook y celular.