Convertidor decimal a binario
Este programa puede parecer perezoso, también intenté iterar a través del vector pero el rendimiento fue deficiente, así que utilicé este enfoque perezoso que tiene más rendimiento
#ifndef BINARY_HH
#define BINARY_HH
/**************************************************************************
* Name: Binary.hh
* Author: Samuel Oseh
* Date: 27/09/2020
* File Info: This file contains class method-function prototypes
* Purpose: Binary Converter is a program that converts a decimal
* to its binary equivalents and also performs other calculations
**************************************************************************/
#include <vector>
#include <string>
class Binary {
public:
Binary( const int &, const char & );
~Binary() {}
Binary( const Binary & );
void printBinary() const;
void toBinary();
char getType() const;
int getDecimal() const;
Binary &operator+=( const Binary &binaryToAdd );
Binary &operator-=( const Binary &binaryToSub );
Binary &operator*=( const Binary &binaryToMul );
Binary &operator/=( const Binary &binaryToDiv );
bool operator==( const Binary &binaryToCompare ) const;
inline bool operator!=( const Binary &binaryToCompare ) const {
return !( *this == binaryToCompare );
}
const Binary &operator=( const Binary &binaryToCopy );
private:
char type;
int decimal;
std::vector< int > binary{};
};
#endif
/**************************************************************************
* Name: Binary.cc
* Author: Samuel Oseh
* Date: 27/09/2020
* File Info: This file contains class method-function definitions
* Purpose: Binary Converter is a program that converts a decimal
* to its binary equivalents and also performs other calculations
**************************************************************************/
#include <iostream>
#include <stdexcept>
#include "Binary.hh"
Binary::Binary( const int &d, const char &t ) {
if ( tolower( t ) == 'd' )
type = t;
else
throw std::invalid_argument( "type must be 'd' only." );
if ( d < 0 )
throw std::invalid_argument( "decimal value must be greater than 0." );
decimal = d;
}
Binary::Binary( const Binary &binaryToCopy ) {
decimal = binaryToCopy.decimal;
type = binaryToCopy.type;
for ( unsigned int counter = 0; counter < binaryToCopy.binary.size(); ++ counter ) {
binary.push_back( binaryToCopy.binary[ counter ] );
}
}
void Binary::toBinary() {
if ( type == 'd' ) {
int val = decimal;
while ( val != 0 ) {
binary.insert( binary.begin(), val % 2 );
val /= 2;
}
}
else {
throw std::invalid_argument( "Invalid type conversion" );
}
}
void Binary::printBinary() const {
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot print binary object without converting it" );
for ( int number : binary ) {
std::cout << number << "";
}
}
char Binary::getType() const {
return type;
}
int Binary::getDecimal() const {
return decimal;
}
Binary &Binary::operator+=( const Binary &binaryToAdd ) {
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
if ( binaryToAdd.binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
int decimalSum = decimal + binaryToAdd.decimal;
Binary *b = new Binary( decimalSum, 'd' );
b->toBinary();
*this = *b;
delete b;
return *this;
}
Binary &Binary::operator-=( const Binary &binaryToAdd ) {
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
if ( binaryToAdd.binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
int decimalSum = decimal - binaryToAdd.decimal;
if ( decimalSum < 0 ) {
throw std::invalid_argument( "Can not perform subtraction from a lesser binary" );
}
Binary *b = new Binary( decimalSum, 'd' );
b->toBinary();
*this = *b;
delete b;
return *this;
}
Binary &Binary::operator*=( const Binary &binaryToMul ) {
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
if ( binaryToMul.binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
int decimalSum = decimal * binaryToMul.decimal;
Binary *b = new Binary( decimalSum, 'd' );
b->toBinary();
*this = *b;
delete b;
return *this;
}
Binary &Binary::operator/=( const Binary &binaryToDiv ) {
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
if ( binaryToDiv.binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
int decimalSum = decimal / binaryToDiv.decimal;
Binary *b = new Binary( decimalSum, 'd' );
b->toBinary();
*this = *b;
delete b;
return *this;
}
bool Binary::operator==( const Binary &binaryToCompare ) const {
if ( decimal == binaryToCompare.decimal )
return true;
return false;
}
const Binary &Binary::operator=( const Binary &binaryToCopy ) {
decimal = binaryToCopy.decimal;
type = binaryToCopy.type;
binary.clear();
for ( unsigned int counter = 0; counter < binaryToCopy.binary.size(); ++ counter ) {
binary.push_back( binaryToCopy.binary[ counter ] );
}
return *this;
}
Respuestas
Visión general
Creo que la parte más reveladora es esta:
int decimal;
Probablemente no sea un número decimal. En la mayoría de las computadoras modernas, esto se almacena como un número binario (aunque en algunas computadoras excesivamente antiguas usaban decimales, pero abandonaron las computadoras decimales en favor de las binarias muy rápidamente).
El problema con su código es que un número es un número. Su base solo es importante cuando la visualizas, la analizas o la guardas. El almacenamiento del número es una abstracción de la que se ha encargado la capa de hardware (el hardware sabe cómo almacenar y realizar operaciones básicas en números enteros). Entonces, lo único para ti es la capa de presentación (impresión y análisis).
Decimal 10:
Binary 1010
Hex 0xA
Todos estos son simplemente la representación visual del mismo concepto. Ya tenemos el concepto de un número entero proporcionado por el lenguaje que intrepresenta un valor.
Revisión de código
El tparámetro de tipo es superfluo aquí.
Binario :: Binario (const int & d, const char & t) {
El valor ya des un número. Solo necesita el tipo si está convirtiendo a partir de una representación visual (es decir, una cadena). De lo contrario, siempre es un número.
No estoy seguro de por qué no admite valores negativos:
if ( d < 0 )
throw std::invalid_argument( "decimal value must be greater than 0."
¿No es tan dificil?
Esto podría simplificarse:
for ( unsigned int counter = 0; counter < binaryToCopy.binary.size(); ++ counter ) {
binary.push_back( binaryToCopy.binary[ counter ] );
}
// Simpler to write:
binary = binaryToCopy.binary;
Si desea almacenar localmente una representación fácil de convertir a texto, puede usar std::bitset<32>.
std::bitset<32> binary;
void Binary::toBinary() {
binary = decimal; // converts it into a bitset.
// bitsset when put on a stream will show 1/0
// Note internally it is just an int.
}
Seguro que es bueno tener una función de impresión.
void Binary::printBinary() const {
Pero en C ++ normalmente usamos operator<<para colocar datos en un flujo de salida. Así que es bueno escribir la función apropiada que lo haga. No puede simplemente llamar a la printBinary()función. Pero necesitará modificar su función de impresión para aceptar una secuencia (puede usarla por defecto std::outpara compatibilidad con versiones anteriores).
void Binary::printBinary(std::ostream& str = std::cout) const {
binary.toBinary(); // You can convert see next section.
out << binary; // Assuming you used std::bitset.
}
friend std::ostream& operator<<(std::ostream& str, Binary const& b)
{
b.printBinary(str);
return str;
}
Puede convertir el número en un método constante.
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot print binary object without converting it" );
El binaryobjeto está almacenando un estado temporal (es decir, no representa el estado del objeto. Representa un valor fácil de imprimir del estado actual. Así que este es un lugar perfecto para marcar un miembro como mutable.
mutable std::bitset<32> binary;
Ahora puede actualizar el estado en una función constante:
Una vez que el valor se ha convertido en un número, su tipo es irrelevante.
char Binary::getType() const {
return type;
}
No devuelve un decimal. Devuelve un número.
int Binary::getDecimal() const {
return decimal;
}
En realidad, se almacena como binario.
Vaya, esto parece mucho trabajo.
Binary &Binary::operator+=( const Binary &binaryToAdd ) {
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
if ( binaryToAdd.binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
int decimalSum = decimal + binaryToAdd.decimal;
Binary *b = new Binary( decimalSum, 'd' );
b->toBinary();
*this = *b;
delete b;
return *this;
}
Primero no creemos tipos dinámicos:
Binary *b = new Binary( decimalSum, 'd' );
b->toBinary();
*this = *b;
delete b;
Esto se puede simplificar a:
Binary b( decimalSum, 'd' );
b.toBinary();
*this = b;
Pero por qué hacer todo eso, por qué no simplificar un paso más y eliminar el objeto intermedio.
decimal += binaryToAdd.decimal;
binary.clear(); // Not sure if you need this but probably.
toBinary();
¿No estás seguro de por qué necesitan estar ya convertidos?
if ( binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
if ( binaryToAdd.binary.size() == 0 )
throw std::invalid_argument( "Cannot add binary object without converting it" );
Solo deshazte de eso.
Lo mismo se aplica aquí:
Binary &Binary::operator-=( const Binary &binaryToAdd ) {
Binary &Binary::operator*=( const Binary &binaryToMul ) {
Binary &Binary::operator/=( const Binary &binaryToDiv ) {
// ^ Note in C++ (unlike C) the & and * go with the type (traditionally).
Implementó la familia de operadores + =. Esto hace que el siguiente paso sea tan simple. Me sorprende que no haya implementado la familia de operadores +.
Binary Binary::operator+(Binary const& rhs) const {
Binary newValue(*this); // copy;
return newValue += rhs; // Add to the copy and return.
}
Esto se puede simplificar:
if ( decimal == binaryToCompare.decimal )
return true;
return false;
A
return decimal == binaryToCompare.decimal;
Si te encuentras haciendo:
if (test) {
return true;
}
else {
return false;
}
This is the same as
return test; // as test must be a boolean value (or convertible to cone).