Dezimal-Binär-Konverter

Sep 28 2020

Dieses Programm mag faul erscheinen. Ich habe auch versucht, den Vektor zu durchlaufen, aber die Leistung war schlecht, deshalb habe ich diesen faulen Ansatz verwendet, der mehr Leistung bietet

#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;
}

Antworten

7 MartinYork Sep 28 2020 at 14:57

Überblick

Ich denke, der aufschlussreichste Teil ist folgender:

        int decimal;

Das ist wahrscheinlich keine Dezimalzahl. In den meisten modernen Computern wird dies als Binärzahl gespeichert (obwohl in einigen sehr alten Computern Dezimalstellen verwendet wurden, aber Dezimalrechner sehr schnell zugunsten von Binärzahlen aufgegeben wurden).

Das Problem mit Ihrem Code ist, dass eine Nummer eine Nummer ist. Die Basis ist nur wichtig, wenn Sie sie visualisieren, analysieren oder speichern. Das Speichern der Nummer ist eine Abstraktion, um die sich die Hardwareschicht gekümmert hat (die Hardware weiß, wie man grundlegende Operationen für Ganzzahlen speichert / ausführt). Das einzige, was Sie tun, ist die Präsentationsebene (Drucken und Parsen).

Decimal 10:
Binary  1010
Hex     0xA

Dies alles ist einfach die visuelle Darstellung desselben Konzepts. Wir haben bereits das Konzept einer Ganzzahl, die von der Sprache bereitgestellt wird intund einen Wert darstellt.


Code-Review

Der tTypparameter ist hier überflüssig.

Binär :: Binär (const int & d, const char & t) {

Der Wert dist bereits eine Zahl. Sie benötigen den Typ nur, wenn Sie aus einer visuellen Darstellung (dh einer Zeichenfolge) konvertieren. Ansonsten ist es immer eine Zahl.


Nicht sicher, warum Sie keine negativen Werte unterstützen:

    if ( d < 0 )
        throw std::invalid_argument( "decimal value must be greater than 0."     

Es ist nicht so schwer?


Dies könnte vereinfacht werden:

    for ( unsigned int counter = 0; counter < binaryToCopy.binary.size(); ++ counter ) {
        binary.push_back( binaryToCopy.binary[ counter ] );
    }

    // Simpler to write:

    binary = binaryToCopy.binary;

Wenn Sie eine einfach zu konvertierende Textdarstellung lokal speichern möchten, können Sie diese verwenden 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.
}

Sicher ist es schön, eine Druckfunktion zu haben.

void Binary::printBinary() const {

In C ++ werden normalerweise operator<<Daten in einem Ausgabestream platziert. Es ist also schön, die entsprechende Funktion zu schreiben, die das macht. Nicht kann es einfach die printBinary()Funktion aufrufen . Aber Sie müssen Ihre Druckfunktion modifizieren , um einen Strom zu übernehmen (Sie es auf Standard kann std::outfür Abwärtskompatibilität.

    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;
    }

Sie können die Zahl in eine const-Methode konvertieren.

    if ( binary.size() == 0 ) 
        throw std::invalid_argument( "Cannot print binary object without converting it" );

Das binaryObjekt speichert den temporären Status (dh es repräsentiert nicht den Status des Objekts. Es stellt einen leicht druckbaren Wert des aktuellen Status dar. Dies ist also ein perfekter Ort, um ein Mitglied als veränderbar zu markieren.

    mutable std::bitset<32>    binary;

Jetzt können Sie den Status in einer const-Funktion aktualisieren:


Sobald der Wert in eine Zahl konvertiert wurde, ist sein Typ irrelevant.

char Binary::getType() const {
    return type;
}

Sie geben keine Dezimalstelle zurück. Sie geben eine Nummer zurück.

int Binary::getDecimal() const {
    return decimal;
}

Es ist tatsächlich als Binärdatei gespeichert, wie Sie wissen.


Wow, das scheint viel Arbeit zu sein.

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;
}

Lassen Sie uns zunächst keine dynamischen Typen erstellen:

    Binary *b = new Binary( decimalSum, 'd' );
    b->toBinary();
    *this = *b;
    delete b;

Dies kann vereinfacht werden, um:

    Binary  b( decimalSum, 'd' );
    b.toBinary();
    *this = b;

Aber warum all das tun, warum nicht noch einen Schritt vereinfachen und das Zwischenobjekt entfernen?

    decimal += binaryToAdd.decimal;
    binary.clear();   // Not sure if you need this but probably.
    toBinary();

Nicht sicher, warum sie bereits konvertiert werden müssen?

    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" );

Lass das einfach los.


Gleiches gilt hier:

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).

Sie haben die Operatorfamilie + = implementiert. Dies macht den nächsten Schritt so einfach. Ich bin überrascht, dass Sie die Operatorfamilie + nicht implementiert haben.

Binary Binary::operator+(Binary const& rhs) const { 
    Binary newValue(*this);  // copy;
    return newValue += rhs;  // Add to the copy and return.
}

Dies kann vereinfacht werden:

    if ( decimal == binaryToCompare.decimal )
        return true;
    return false;

Zu

    return decimal == binaryToCompare.decimal;

Wenn Sie sich selbst tun:

     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).