git » metnum-tp1.git » commit 8c8eb38

Commit inicial

author Alberto Bertogli
2010-08-30 16:54:12 UTC
committer Alberto Bertogli
2010-08-30 16:54:12 UTC

Commit inicial

Esta implementada la aritmética con truncamiento, y hay una calculadora para
poder probarla.

.gitignore +3 -0
Makefile +15 -0
aritmetica.cpp +78 -0
aritmetica.hpp +47 -0
calc.cpp +44 -0

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..eac4c51
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+calc
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6f07f6c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+
+CXXFLAGS += -Wall -std=c++98 -pedantic -Wno-long-long
+
+OBJS = aritmetica.o calc.o
+
+default: calc
+
+all: default
+
+calc: $(OBJS)
+	$(CXX) $(CXXFLAGS) $(OBJS) -o calc
+
+clean:
+	rm -f $(OBJS) calc
+
diff --git a/aritmetica.cpp b/aritmetica.cpp
new file mode 100644
index 0000000..1257d8b
--- /dev/null
+++ b/aritmetica.cpp
@@ -0,0 +1,78 @@
+
+#include <stdio.h> // XXX REMOVE
+#include <stdint.h>
+#include "aritmetica.hpp"
+
+uint64_t to_u64(double n)
+{
+	uint64_t *p;
+	p = (uint64_t *) &n;
+	return *p;
+}
+
+double to_double(uint64_t n)
+{
+	double *p;
+	p = (double *) &n;
+	return *p;
+}
+
+double trunc(int prec, double n)
+{
+	/* Sabemos que el double tiene 64 bits en total, de los cuales se usan
+	 * 52 para la mantisa. Para recortar, dejamos en 0 todo lo que excede
+	 * a la precision pedida, aplicando una máscara. */
+
+	/* Armamos la máscara */
+	uint64_t mask = 0xFFFFffffFFFFffff;
+	mask = mask << (52 - prec);
+
+	uint64_t t = to_u64(n) & mask;
+
+	return to_double(t);
+}
+
+
+/*
+ * Clase número
+ */
+
+numero::numero(int prec, double real)
+{
+	this->prec = prec;
+	this->real = trunc(prec, real);
+}
+
+/* Todas las operaciónes son iguales, por lo que armamos una macro para
+ * crearlas y ahorrarnos el copy-paste */
+#define DEF_OP(OP) \
+	numero numero::operator OP (const numero &b) const \
+	{ \
+		return numero(this->prec, \
+				trunc(this->prec, this->real) \
+					OP \
+				trunc(this->prec, b.real)); \
+	}
+
+DEF_OP(+)
+DEF_OP(-)
+DEF_OP(*)
+DEF_OP(/)
+
+numero numero::operator = (double n)
+{
+	this->real = trunc(this->prec, n);
+	return *this;
+}
+
+numero numero::operator = (numero n)
+{
+	this->prec = n.prec;
+	this->real = n.real;
+	return *this;
+}
+numero::operator double() const
+{
+	return this->real;
+}
+
diff --git a/aritmetica.hpp b/aritmetica.hpp
new file mode 100644
index 0000000..112b55c
--- /dev/null
+++ b/aritmetica.hpp
@@ -0,0 +1,47 @@
+
+#ifndef _ARITMETICA_HPP
+#define _ARITMETICA_HPP
+
+/* Devuelve un uint64_t con el contenido del double, porque el cast no es tan
+ * pavote. */
+uint64_t to_u64(double n);
+
+/* Devuelve un double con el contenido del uint64_t, porque el cast no es tan
+ * pavote. */
+double to_double(uint64_t n);
+
+/* Recorta la precision del double dado, devuelve un double "recortado". */
+double trunc(int prec, double n);
+
+class numero
+{
+public:
+	numero(int prec = 52, double real = 0);
+
+	// Aritmeticas
+	numero operator + (const numero &b) const;
+	numero operator - (const numero &b) const;
+	numero operator * (const numero &b) const;
+	numero operator / (const numero &b) const;
+
+	// Unario
+	//numero operator - () const;
+
+	// Asignación
+	numero operator = (double n);
+	numero operator = (numero n);
+
+	// Cast to a double
+	operator double() const;
+
+private:
+	// Precision
+	int prec;
+
+	// Double utilizado para almacenar y operar, siempre va a estar en la
+	// precision de prec
+	double real;
+};
+
+#endif // ifdef _ARITMETICA_HPP
+
diff --git a/calc.cpp b/calc.cpp
new file mode 100644
index 0000000..d21400b
--- /dev/null
+++ b/calc.cpp
@@ -0,0 +1,44 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "aritmetica.hpp"
+
+int main(int argc, char *argv[])
+{
+	if (argc != 5) {
+		printf("Uso: calc <prec> <nro 1> {+-*/} <nro2>\n");
+		return 1;
+	}
+
+	int prec = atoi(argv[1]);
+	numero a(prec, strtod(argv[2], NULL));
+	char op = argv[3][0];
+	numero b(prec, strtod(argv[4], NULL));
+
+	printf("a =\t %.60f 0x%lx\n", (double) a, to_u64(a));
+	printf("b =\t %.60f 0x%lx\n", (double) b, to_u64(b));
+
+	numero res;
+	switch (op) {
+	case '+':
+		res = a + b;
+		break;
+	case '-':
+		res = a - b;
+		break;
+	case '*':
+		res = a * b;
+		break;
+	case '/':
+		res = a / b;
+		break;
+	default:
+		printf("Error: operacion desconocida\n");
+		return 1;
+	}
+
+	printf("a %c b =\t %.60f 0x%lx\n", op, (double) res, to_u64(res));
+
+	return 0;
+}