author | Alberto Bertogli
<albertito@blitiri.com.ar> 2010-08-30 16:54:12 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2010-08-30 16:54:12 UTC |
.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; +}