Calculadora Científica Con Java FX

Hola 🙂 , he estado practicando con Java cómo crear una calculadora científica; he probado Swing y FX. Me he decantado por FX no sólo porque se pueda pseudo-utilizar CSS, sino también porque: Scene-Builder es mucho más utilizable que el editor de NetBeans, y no te pone montón de código inútil. En general; FX es mucho mejor que Swing porque no es tan intrusivo en tu código; además de poder configurar tu UI mucho más fácil si te defiendes con CSS.

La calculadora opera tanto con operaciones elementales como en científicas. Me faltan 2 cosas a implementar:

Trabajar con fracciones->En esto ya tengo la clase Fracciones hecha con Java, debo añadir los botones con sus acciones y listo. No lo he terminado porque hace mucho calor.

Trabajar con paréntesis->Esto es ya más peliagudo, necesito un parseador, he encontrado mXparser; debo leer su documentación y practicar por consola antes de llevarlo a la aplicación.

Hacer la app usable en Android-> Debo averiguar cómo se establece el puente entre FX y Android, sospecho que me va a dar muchos dolores de cabeza.

Con todo eso que quiero averiguar / aprender, la calculadora es totalmente funcional y si tiene algún bug no creo que sea muy grave. Me gustaría saber cómo hacer para que su Look & Feel se parezca a una Casio, es decir; más realista. En fin, poco a poco.

Me ha dado muchos problemas para calcular algunos ángulos fundamentales con las funciones trigonométricas, ya que Java como la mayoría de lenguajes de programación dan resultados aproximados si usas double. Para el cálculo del factorial, combinaciones y variaciones he tenido que cambiar el tipo entero a Big Integer para que calculase algo decente.

La configuración de la interfaz es muy cómodo con SceneBuilder, he podido arrastrar/soltar un GridPane para ponerle dentro todos los botones, esto con Swing es una pesadilla (si lo quieres fácil debes pagar mucho). Como SceneBuilder te crea un fichero .fxml que sólo debes llamar desde tu código, hace que casi todo lo que se relaciona con la IU esté totalmente separada de la lógica de la app. FX te permite trabajar fácilmente con el modelo MVC (sobre todo con Netbeans):

1 Fichero fxml-> lo puedes crear con SceneBuilder

2 Fichero clase ppal. -> Contiene la clase ppal. con el método main y la incialización de la Stage y la Scene. Con llamadas para cargar los ficheros fxml y css.

3 Fichero Controlador -> Te crea el esqueleto Netbeans y tú lo vas rellenando con el código necesario para que el usuario pueda interactuar con la IU.

4 Fichero CSS -> El fichero para poder cambiar colores, tamaños etc de la app.

En fin, al principio cuesta un poco hacer las cosas con FX pero luego de unos días googleando y preguntando obtienes mejores resultados y más rápidos que con Swing.

Aquí dejo el código del fichero controlador:

[java]

package fxcalculator;

import java.math.BigInteger;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;

/**
*
* @author lopez
*/
public class fxmlCalculatorController implements Initializable {
double number1 = 0.;
double number2 = 0.;
double solution;
BigInteger soltn;
long n1 = 0;
long n2 = 0;
String operation = “”;

@FXML
private TextField txtDisplay;

@FXML
private void Btn7OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “7”);
}
@FXML
private void Btn8OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “8”);
}
@FXML
private void Btn9OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “9”);
}
@FXML
private void Btn4OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “4”);
}
@FXML
private void Btn5OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “5”);
}
@FXML
private void Btn6OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “6”);
}
@FXML
private void Btn3OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “3”);
}
@FXML
private void Btn2OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “2”);
}
@FXML
private void Btn1OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “1”);
}
@FXML
private void Btn0OnAction(ActionEvent event) {
txtDisplay.setText(txtDisplay.getText() + “0”);
}
@FXML
private void BtnDecimalPointOnAction(ActionEvent event) {
if(!txtDisplay.getText().contains(“.”))
txtDisplay.setText(txtDisplay.getText() + “.”);
}
@FXML
private void BtnPlusMinusOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(!n.contains(“-“))
txtDisplay.setText(“-” + n);
}
@FXML
private void BtnClearOnAction(ActionEvent event) {
txtDisplay.setPromptText(“0”);
txtDisplay.setText(“”);
}
@FXML
private void BtnClearCharOnAction(ActionEvent event) {
String n = txtDisplay.getText();
String nn;
nn = n.substring(0, n.length()-1);
txtDisplay.setText(nn);
}
@FXML
private void BtnPIOnAction(ActionEvent event) {
txtDisplay.setText(String.valueOf(Math.PI));
}
@FXML
private void BtnEOnAction(ActionEvent event) {
txtDisplay.setText(String.valueOf(Math.E));
}
@FXML
private void BtnSumOnAction(ActionEvent event) {
operation = “suma”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number1 = Double.parseDouble(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnSubtractOnAction(ActionEvent event) {
operation = “resta”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number1 = Double.parseDouble(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnProductOnAction(ActionEvent event) {
operation = “producto”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number1 = Double.parseDouble(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnDivOnAction(ActionEvent event) {
operation = “division”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number1 = Double.parseDouble(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnSquareRootOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.sqrt(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnCubicRootOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.cbrt(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnModulusOnAction(ActionEvent event) {
operation = “modulo”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number1 = Double.parseDouble(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnPower2OnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.pow(nn, 2);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnPower3OnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.pow(nn, 3);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnPowXnOnAction(ActionEvent event) {
operation = “potencia”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number1 = Double.parseDouble(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnExp10OnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.pow(10, nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnExpEOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.pow(Math.E, nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnLogOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.log10(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnLnOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.log(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnInverseOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = 1 / nn;
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnFactorialOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
long nn = Long.parseLong(n);
BigInteger m;
m = factorial(nn);
n = String.valueOf(m);
txtDisplay.setText(n);
}
}
@FXML
private void BtnCombinationOnAction(ActionEvent event) {
operation = “combination”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
n1 = Integer.parseInt(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnVariationOnAction(ActionEvent event) {
operation = “variation”;
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
n1 = Integer.parseInt(txtDisplay.getText());
txtDisplay.setText(“”);
txtDisplay.setPromptText(“”);
}
}
@FXML
private void BtnDegMinSecOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
n = degreesConversor(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnSineOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
if(nn >= 360 || nn < 0) nn %= 360;
if(nn % 180 == 0) nn = 0;
else nn = Math.sin(Math.toRadians(nn));
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnCosineOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
if(nn >= 360 || nn < 0) nn %= 360;
if(nn == 90 || nn == 270) nn = 0;
else nn = Math.cos(Math.toRadians(nn));
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnTangentOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
if(nn >= 360 || nn < 0) nn %= 360;

if(nn == 0 || Math.abs(nn) == 180) nn = 0;
else if(Math.abs(nn) == 45 || Math.abs(nn) == 225) nn = 1;
else if(Math.abs(nn) == 135 || Math.abs(nn) == 315) nn = -1;
else if(Math.abs(nn) == 90 || Math.abs(nn) == 270) nn = Double.NaN;
else nn = Math.tan(Math.toRadians(nn));
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnASineOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.toDegrees(Math.asin(nn));
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnACosineOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.toDegrees(Math.acos(nn));
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnATangentOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.toDegrees(Math.atan(nn));
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnHypSineOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.sinh(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnHypCosineOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.cosh(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnHypTangentOnAction(ActionEvent event) {
String n = txtDisplay.getText();
if(n.length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
double nn = Double.parseDouble(n);
nn = Math.tanh(nn);
n = String.valueOf(nn);
txtDisplay.setText(n);
}
}
@FXML
private void BtnEqualsOnAction(ActionEvent event) {
if(txtDisplay.getText().length() == 0){
txtDisplay.setText(“Please, insert digits”);
}
else {
number2 = Double.parseDouble(txtDisplay.getText());
switch (operation) {
case “suma”:
solution = number1 + number2;
txtDisplay.setText(String.valueOf(solution));
break;
case “resta”:
solution = number1 – number2;
System.out.println(solution);
txtDisplay.setText(String.valueOf(solution));
break;
case “producto”:
solution = number1 * number2;
txtDisplay.setText(String.valueOf(solution));
break;
case “division”:
solution = number1 / number2;
txtDisplay.setText(String.valueOf(solution));
break;
case “potencia”:
solution = Math.pow(number1, number2);
txtDisplay.setText(String.valueOf(solution));
break;
case “modulo”:
solution = number1 % number2;
txtDisplay.setText(String.valueOf(solution));
break;
case “combination”:
n2 = Long.parseLong(txtDisplay.getText());
soltn = combinatorial(n1, n2);
txtDisplay.setText(String.valueOf(soltn));
break;
case “variation”:
n2 = Long.parseLong(txtDisplay.getText());
soltn = variations(n1, n2);
txtDisplay.setText(String.valueOf(soltn));
break;
default:
break;
}
}
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}

public static BigInteger factorial(long n) {
if (n == 0) return BigInteger.valueOf(1);
BigInteger fact = BigInteger.valueOf(1);
for (int i = 1; i <= n; i++) {
fact = fact.multiply(BigInteger.valueOf(i));
}

return fact;
}
public static BigInteger combinatorial(long m, long n) {
return factorial(m).divide(factorial(n).multiply(factorial(m – n)));
}
public static BigInteger variations(long m, long n) {
return factorial(m).divide(factorial(m – n));
}
public static String degreesConversor(double x){
int integer_part = (int) Math.floor(x);
double decimal_part = x – Math.floor(x);
int deg, min, secs;
String expression;

min = Math.abs((int) (decimal_part * 60.));
secs = Math.abs((int) ((decimal_part * 60. – Math.floor(decimal_part * 60.)) * 60.));
deg = integer_part;

if(secs >= 60) {secs -= 60; min += 1;}
if(min >= 60) {min -= 60; deg += 1;}
if(deg >= 360) deg %= 360;
if(deg < 0) deg += 360;

expression = String.valueOf(deg) + “º ” + String.valueOf(min) +
“‘ ” + String.valueOf(secs) + “””;
return expression;
}
}

 

[/java]

Todo el código se puede descargar en mi GitHub:

[descarga]

DESCARGAR CÓDIGO

[/descarga]

Calculator

Dibujando Polígono De Las Raíces Unidad Con Python 3.5

Hola :-). Pongámonos en situación, tomemos por ejemplo la ecuación polinómica x^{11}+1=0, a la cual le queremos dibujar sus raíces unidad onceavas en su polígono regular de 11 lados, el cual esta inscrito en la circunferencia unidad. Lo vamos a dibujar con Python utilizando Matplotlib. El código no es muy complicado, para facilitar un poco las cosas utilizamos Numpy, ya que nos permitirá trabajar de una manera óptima con las matrices. El código es el siguiente:
[python]
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

def unit_circle(n, title=”):
vertices = np.empty(shape=0)
for k in np.arange(n):
vertices = np.append(vertices, [[np.cos((2 * k + 1) / n * np.pi)],
[np.sin((2 * k + 1) / n * np.pi)]])

vertices = vertices.reshape((n, 2))
font = {‘family’: ‘serif’,
‘color’: ‘darkgreen’,
‘weight’: ‘normal’,
‘size’: 16,
}
plt.subplot(aspect=’equal’)
plt.axis(‘off’)
plt.title(r’$Unit;Roots;Polygon;With;$’ + title)
plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)
plt.arrow(0., -1.4, 0., 2.8, fc=”k”, ec=”k”, head_width=0.05, head_length=0.1, zorder=2)
plt.arrow(-1.4, 0., 2.8, 0., fc=”k”, ec=”k”, head_width=0.05, head_length=0.1, zorder=2)
plt.text(1.35, .1, r’$X$’, fontdict=font)
plt.text(.1, 1.35, r’$Y$’, fontdict=font)
circle = plt.Circle((0, 0), 1, color=’b’, lw=2, fill=False, zorder=1)
poly = Polygon(vertices, facecolor=’w’, edgecolor=’r’, lw=2, aa=True, joinstyle=’bevel’)
plt.plot(*zip(*vertices), color=’brown’, marker=’o’, markersize=8, ls=”)
plt.gcf().gca().add_artist(circle)
plt.gcf().gca().add_artist(poly)
plt.show()

if __name__ == ‘__main__’:
unit_circle(11, title=r’$P(x)=x^{11}+1$’)

[/python]
El resultado lo podemos ver en la imagen siguiente:
raizunidad//embedr.flickr.com/assets/client-code.js

El código en sí no es difícil, es limpio y gracias a que lo hemos creado con una función podemos dibujar el polinomio para cualquier grado.
Saludos 🙂

Resolver Sistema Tridiagonal Disperso Con Scipy, Python

Hola 🙂 , como paso previo para poder resolver una E.D.P del calor se necesita saber resolver sistemas tridiagonales lineales dispersos. Con Python es relativamente sencillo si utilizamos las librerías Scipy, con las cuales podemos implementar matrices dispersas con funciones específicas como dia_matrix.
Una vez implementada la matriz dispersa de nuestro sistema tan sólo hay que elegir el método para resolverlo: descomposición LU, Choleski, etc. En mi caso he utilizado la descomposición LU (también conocida como Algoritmo de Crout) y que viene implementada con Scipy. Éste método es eficiente para resolver la ecuación del calor, además; nuestra matriz de coeficientes dispersa de la ecuación del calor es tridiagonal y cumpliendo las condiciones necesarias para que funcione el algoritmo de Crout: semidefinida positiva, etc.
He realizado un pequeño algoritmo en Python 3 y Scipy en el que vemos cómo resolver primero un sistema lineal cualquiera 5 x 5 con Crout y luego cómo aplicarlo con un sistema 7 x 7 en el que nuestra matriz de coeficientes es una matriz dispersa tridiagonal.
Pongo el algoritmo aquí con todo explicado en el mismo código, lo he escrito en inglés, pero cualquier conocedor del tema no debe tener complicaciones para entenderlo.
[python]
from scipy import linalg, sparse, array

def crout(A, b):
“””
Find out the solution of a linear system using the LU decomposition, also knnown
as The Crout Algorithm.
:param A: Coefficient Matrix
:param b: Independent column matrix terms
:return: A solution matrix of a linear system
“””
lu = linalg.lu_factor(A)
solution = linalg.lu_solve(lu, b)
return solution

def tridiagonal_system(data, diagonals, rows, columns, b):
“””
Find out the solution of a sparse tri-diagonal linear system using The Crout Algorithm
:param data: the diagonal elements of a coefficient tri-diagonal matrix
:param diagonals: a vector to specify the positions of the diagonals in a tri-diagonal matrix
:param rows: the number of equations of the linear system
:param columns: the number of unknowns of the linear system
:param b: Independent column matrix terms
:return: A solution matrix of a sparse tri-diagonal linear system
“””
A = sparse.dia_matrix((data, diagonals), shape=(rows, columns)).todense()
return crout(A, b)

def main():
A = array([[4, 5, 9, 2, 8], [9, 7, 8, 12, 3], [2, 5, 7, 2, 4], [2, 6, 8, 4, 8], [1, 7, 4, 3, 7]])
b = array([2, 9, 7, 4, 5])

print(‘The solution of the linear system using The Crout Algorithm is:’)
print(crout(A, b))

diag_down = array([1]).repeat(7) # The -1 diagonal
diag_main = array([2]).repeat(7) # The main diagonal
diag_up = array([3]).repeat(7) # The 1 diagonal
diagonals = array([-1, 0, 1]) # The positions of our diagonals in the coefficient mattrix
data = array([diag_down, diag_main, diag_up])

b2 = array([2, 9, 7, 4, 5, 6, 3])
print(‘The solution of the tridiagonal linear system using The Crout Algorithm is:’)
print(tridiagonal_system(data, diagonals, 7, 7, b2))

main()
[/python]
Se puede apreciar que el código es corto y lo suficientemente claro para poder aplicarlo con eficiencia. La salida del mismo es la siguiente:
[terminal]
The solution of the linear system using The Crout Algorithm is:
[-0.46742021 1.76130319 0.64827128 -0.02393617 -1.34042553]
The solution of the tridiagonal linear system using The Crout Algorithm is:
[-5.16071429 4.10714286 1.98214286 -0.35714286 0.91071429 1.17857143
0.91071429]
[/terminal]

En cuanto tenga tiempo escribiré sobre cómo resolver y dibujar la ecuación del calor, reutilizando éste código, aplicando el Algoritmo de Crank-Nicolson y las librerías Matplotlib de Python 3.
Saludos 🙂

Dibujando Bob Esponja Con HTML 5 Y Canvas

Hola  🙂

Hace día vi un vídeo de cómo dibujar a Bob Esponja con CSS3 pero sin usar Canvas. El vídeo está muy bien explicado y esta realizado por Falcon Masters, canal de YouTube que sigo ya hace tiempo. El vídeo es éste:

Podéis consultar  todo el código en el siguiente artículo de su blog:

[web]

ARTÍCULO BOB ESPONJA EN FALCON MASTERS

[/web]

El caso es que pensé que estaría bien hacerlo pero utilizando Canvas y JavaScript, ya que así me evitaba estar pensando con los distintos tipos de position, display y z-index; los cuales son un verdadero engorro. También pensé que era  una forma amena de aprender a utilizar Canvas, y acerté. Con esto he aprendido a diferenciar cómo utilizar curvas Bezier. En concreto, la función quadraticCurveTo es un caso particular para dibujar parábolas usando Bezier, y que he utilizado para dibujar la boca. Para dibujar la boca con ésta función hay que colocar el punto de  control  como el punto medio entre el punto de partida y el de parada.

El código lo he subido a Code Pen:

[web]

CÓDIGO BOB ESPONJA CON CANVAS

[/web]

Ya ya, no tiene brazos y piernas 😀 , se las iré poniendo poco a poco y actualizando el código en Code Pen 😉

Saludos 🙂

Calculadora Con PyQt5

Hola 🙂

Estos días he estado ocupado aprendiendo PyQt5. No parece difícil, de hecho es la primera que con un lenguaje de programación logro enterarme más de cómo hacer aplicaciones ventana. No me extraña, programar con Python simplifica mucho las cosas, haces lo mismo pero el lenguaje es mucho más claro y simplificado. Si lo tuviese que hacer con QT y C++ no se si habría llegado al objetivo.

En fin, el programa es una sencilla pero completa calculadora científica, totalmente funcional; no como muchas que hay por ahí en tutoriales que son un desastre. La calculadora cuenta con cálculos trigonométricos, hiperbólicos: senos, arcosenos, senos hiperbólicos, cosecantes, etc. Transforma radianes a grados, minutos y segundos. Luego tiene los logaritmos, las exponenciales y las raíces cuadradas, cúbicas y n-esima. Calcula la potencia n-ésima de un número y el inverso de un número. Obviamente suma, resta, divide y multiplica.

Lleva incorporada 2 teclas para calcular combinaciones y variaciones de n elementos. También calcula el factorial, el porcentaje y el resto de una división. He incluido tres teclas que son 3 constantes matemáticas conocidas: pi, e y el número áureo.

En la pantalla de resultados aparecen mensajes de error matemáticos cuando se producen, como la división por cero.

En Python realizar el sen(180) directamente no da cero exacto debido a que trabaja con pi, igual pasa con cos(90), etc; en el código del programa he añadido las instrucciones necesarias para que no pase esto. Además, al pasar a grados sexagesimales he añadido una función para que los reduzca todos a la primera vuelta y en sentido positivo.

Seguro que faltan más cosas, como los paréntesis y resultados en forma de fracciones, eso vendrá en una segunda versión mejorada 😉 estoy todavía en el primer escalón de aprendizaje 😀

Para que la calculadora sea lo más vistosa posible le he cambiado su aspecto utilizando CSS, He añadido un fichero CSS al código para cambiarle su aspecto: color de fondo, botones con bordes redondeados, efecto hover en los botones, cambio de estilo en los tooltips, etc.  También lo he hecho para el MessageBox para el About del programa.

La plantilla del programa la he realizado con QtDesigner (menos la del QMessageBox que lo he inyectado directamente al código) así que el fichero ui que me genera lo he pasado a código python. No he puesto directamente los códigos css en QtDesigner, es mucho mejor hacerte un fichero css a parte y llamarlo desde el código de tu clase python.

Las teclas de caracteres matemáticos como el signo de la raíz cuadrada lo he realizado insertando directamente su código unicode utf-8 para que no hayan problemas de compatibilidad.

Ahora mismo lo que me falta por hacer es poder hacerle un ejecutable para Windows, lo he intentado con QtDeploy pero ni caso, y hay muy poca información sobre el tema. Para Linux no hace falta hacer gran cosa para que funcione, tan sólo instalar PyQt5 (sus librerías de desarrollo) y listo, ya que no utilizo paquetes de terceros para el código. Me he apañado con las librerías Math y Decimal. La de Decimal la recomiendo muy mucho para utilizarla, te soluciona muchos quebraderos de cabeza para la obtención de resultados. A mi me ha servido mucho para que cuando haces, por ejemplo; 6 + 8 aparezca en la calculadora 14 y no 14.0.

La verdad es que me ha costado mucho realizar el programa porque para aprender PyQt lo he hecho con un libro basado en PyQt4, con lo que las señales y conexiones no se hacen igual, ahora con PyQt5 son mucho más sencillas. Para lo del CSS he tenido que googlear mogollón, para ver cuál era la mejor forma de añadirlo al código, y también pensar por mi cuenta cuál era la mejor forma, o la que me funcionase. Lo de los símbolos matemáticos también me ha costado mucho solucionarlo correctamente. Pero lo que más me esta costando es lo del qtdeploy, no hay casi nada de información, y la poca que hay  no me entero un carajo 😀

Todo el código lo puedes descargar con total libertad desde mi repositorio de GitHub, también puedes colaborar en su mejora 😉

[web]

DESCARGAR CÓDIGO CALCULADORA

[/web]

Una pequeña muestra de la calculadora en vídeo garrulo 😀

Saludos 🙂

Los niños de la mochila en el pupitre en los institutos

Hola 🙂

Harto estoy de ver y escuchar opiniones desde los medios de comunicación sobre el fracaso escolar en España. En esencia todos hablan de lo mismo, que la educación se ha politizado de tal forma que salimos a reforma escolar por legislatura. Sí, ese es un tumor maligno de la educación.

Pero hay otro problema no menor que esta gangrenando el sistema educativo (su calidad). Hablo de esos chicos/as que van al instituto para no hacer nada. Te plantan la mochila en la mesa, o se sientan en su pupitre vacío y no hacen nada de nada; interés infinito negativo. Mas o menos el problema empieza a aparecer en 2º E.S.O. (también en 1º) y se agrava mucho en 3º con lo del PCPI (o PQPI).

Son chavales que hasta que no cumplen los  16 no pueden abandonar la enseñanza, por ser obligatoria. Están en clase sin hacer absolutamente nada; bueno sí hacen algo, charrar porque se  aburren los escasos 50 minutos que dura una clase. El profesor puede  hacer muy poco ante este problema, como mucho poner partes, notificar  a los padres por tamagochi, o mandarlos a la sala de guardia. A muchos padres de estos chavales/as les preocupa muy poco la educación de sus hijos/as, así que el problema empieza a engrandecerse.

A causa del PCPI te puedes encontrar con un curso de 3º E.S.O. de hasta 7 u 8 abstenciones en la asignatura pero que asisten al aula. Al ser tantos hablan, y como son tantos no puedes poner partes a todos o expulsarlos, porque viene la directiva del instituto y culpa al profesor por no saber tenerlos en  clase. Cuando la realidad es que la directiva no quiere el marrón por si viene el Inspector. También te deja  a ti el marrón porque al expulsarlos o ponerles partes deben llamar a los padres. Sólo si el problema es grave acceden.

Perdonen ustedes, pero en un instituto un profesor va a impartir  su asignatura y no a hacer de niñera de los que no quieren estudiar. Actualmente lo que debería pasar como normal no pasa. Educados deben venir de casa por sus padres y familiares. El profesor de mate va a dar  mates, el de lengua lengua y así sucesivamente. Y por supuesto a enseñar y aguantar comportamientos normales de rebeldía de los jóvenes. Pero no vamos a aguantar que si le dices a un chico/ca que saque los “trastos” y trabaje te conteste mal, te amenace, etc.; y luego muchas directivas escolares se desentienden del problema.

Para aquellos que no sepan que es el PCPI es una forma de 4º E.S.O. con conocimientos mínimos para que los escolares se puedan sacar el graduado escolar. Se les dice que ese graduado es igual que el standard pero más fácil. En muchos centros se les apunta desde 3º E.S.O. para 4º, lo cual conlleva a muchos alumnos del tipo “cartera en el pupitre”. Aquí entran todo tipo de alumnos, desde los que tienen verdaderos problemas para sacar el curso y se esfuerzan; hasta los que pasan de todo y se les mete en el PCPI para que no estén en el 4º E.S.O. En realidad el PCPI esta creado para los que les cuesta y se esfuerzan, pero también entran los que no porque a los políticos les interesa maquillar el fracaso escolar; y una forma sencilla es con el PCPI.

Los chavales se creen que el PCPI es igual que aprobar 4º E.S.O. pero no es del todo cierto. Supongamos dos personas que van a una empresa a pedir trabajo y dejan su currículum y su título del graduado escolar. Pero supongamos que la empresa les pide las notas de las asignaturas; o se entera que una de ellas es de PCPI y la otra no. Sospecho que la empresa empezará a subestimar al del PCPI a no ser que le vea cualidades de digamos “echao pa lante”. Eso es así, es la vida real, y no la que nos intentan hacer ver los políticos y periodistas.

En fin, un problema tabú para no hablarlo en medios de comunicación, o escribirlos en internet; pero del que muchos profesores se quejan en las charlas en los institutos. Todos se vendan los ojos, todos miran a otra parte, pero la gangrena se extiende, es más rápida que el cáncer, y puede matar antes a la educación. Por ahora la educación ya lleva 2 piernas amputadas por este problema.

Saludos 🙂

Tu Dios De Los Mil Rostros

¡Genuflexiónate! , ¡genuflexiónate! , te lo exhorto.
Soy tu dios de los mil rostros;
ahora soy democracia, ahora soy tiranía …
¡Lacérate!, ¡lacérate!, me complaces.
Quiero llegar al orgasmo contemplando tu miseria.
Ahora soy un político, ahora soy un periodista …
¡Arrástrate! ¡Arrástrate!, empiezo a correrme.
No quiero tocarte, tus miserias me dan asco;
aunque me pongo lividinoso contemplando tus patéticos imploros.
¡Reza por mi!, ¡reza ante mi!, con cándida devoción.
Soy tu dios de los mil rostros;
ahora soy un banquero, ahora soy un pedófilo …
Veo tus fervorosas auto-mutilaciones y consumo el acto.
Vuelve a empezar el ciclo, porque soy tu dios …
tu dios de los mil rostros. Témeme con esperanza.
Ahora soy un ministro de vuestras idiotas religiones …
Eres mío, me perteneces en alma y corazón …
No te mataré, tú te matarás en cada ciclo.
Una vez serás mujer, otras hombre, otras infante.
Igual da, morirás y matarás …
porque yo soy tu dios de los mil rostros.

Autor: Tobal