C++ Breukenklasse

Ik moet een klasse maken met de naam Fractiesmet 2 privévelden Teller, Noemer. En een openbare constructor die Teller en Noemer standaard op 1 zet. Ik heb 4 ledenfuncties opgenomen in mijn klas Fracties: Sum, Difference, Product, Division.

Dan weet ik niet wat ik nu moet doen. Waarom toont het boek breukequivalenten? Wat heb ik daar mee te maken? Ik denk dat een zeer belangrijke vraag zou zijn, welke parameters moeten mijn lidfuncties aannemen?

En wat zou een goede manier zijn om de noemer van 0 te verbieden? Uitzondering weggooien of forceren om gelijk te zijn aan 1?

Probleem #5

Hier is de volledige broncode voor vraag #5 en #6 (niet getoond) na dagenlang met het probleem te hebben geworsteld.Vragen #6 zojuist vraagt ​​om de grootste gemene delerfunctie te implementeren om breuken in een vereenvoudigde vorm te retourneren. Dus hier is het…

Als je denkt dat er een manier is om deze code te optimaliseren, hoor ik graag je reacties!

#include <iostream>
using namespace std;
class Fraction
{
private:
    int numerator, denominator; 
public:
    Fraction()
    {
        numerator = 1;
        denominator = 1;
    }
    Fraction(int n, int d)
    {
        numerator = n;
        if (d==0) 
        {
            cout << "ERROR: ATTEMPTING TO DIVIDE BY ZERO" << endl;
            exit(0); // will terminate the program if division by 0 is attempted
        }
        else
            denominator = d;
    }
    /*In the following functions I am dividing both numerator and denominator by the gcd function.
    GCD function accepts both numerator and denominator values. If we had 2 fractions, 1/2 and 1/4
    and we passed it into the Sum, the result would be n=6 and d=8. These are the values that GCD
    function will accept, find greatest common divisor and return the integer value of 2. In my case 
    am diving both numerator and denominator on the same line by the greatest common divisor. Although 
    it probably would be more efficient to create a local int variable and store GCD value in it, but
    for such small program it shouldn't make any difference.*/
    Fraction Sum(Fraction otherFraction)
    {
        int n = numerator*otherFraction.denominator+otherFraction.numerator*denominator;
        int d = denominator*otherFraction.denominator;
        return Fraction(n/gcd(n,d),d/gcd(n,d));
    }
    Fraction Difference(Fraction otherFraction)
    {
        int n = numerator*otherFraction.denominator-otherFraction.numerator*denominator;
        int d = denominator*otherFraction.denominator;
        return Fraction(n/gcd(n,d),d/gcd(n,d));
    }
    Fraction Product(Fraction otherFraction)
    {
        int n = numerator*otherFraction.numerator;
        int d = denominator*otherFraction.denominator;
        return Fraction(n/gcd(n,d),d/gcd(n,d));
    }
    Fraction Division(Fraction otherFraction)
    {
        int n = numerator*otherFraction.denominator;
        int d = denominator*otherFraction.numerator;
        return Fraction(n/gcd(n,d),d/gcd(n,d));
    }
    // I got the GCD algorithm from the following source:
    // Source C#: http://www.ww.functionx.com/csharp2/examples/gcd.htm
    int gcd(int n, int d)
    {
        int remainder;
        while (d != 0)
        {
            remainder = n % d;
            n = d;
            d = remainder;
        }
        return n;
    }
    void show() // Display method
    {
        if (denominator == 1) // e.g. fraction 2/1 will display simply as 2
            cout << numerator << endl;
        else
            cout << numerator << "/" << denominator << endl;
    }
};
int main()
{
    Fraction a(1,2);
    Fraction b(1,4);
    Fraction c;
    c = a.Sum(b); // Result: 3/4
    c.show();
    c = a.Difference(b); // Result: 1/4
    c.show();
    c = a.Product(b); // Result: 1/8
    c.show();
    c = a.Division(b); // Result: 2
    c.show();
    return 0;
}

Antwoord 1, autoriteit 100%

Misschien wil je beginnen met alleen het eerste deel, de klasse maken met twee constructors, één als ze de twee getallen geven en één die standaard 1is.

Schrijf dan de vier functies op, de opdracht is leuk genoeg om je de vergelijkingen te geven.

Als een noemer ooit gelijk is aan nul, zou ik een uitzondering maken, want dat is iets dat de gebruiker mogelijk kan oplossen. Als je kunt laten zien waardoor het nul is geworden, bijvoorbeeld als ze (1/2)/(0/4) delen, dan is je noemer nul, wat een foutconditie zou moeten zijn.

Een probleem waar u naar wilt kijken, is of dit onveranderlijk is, dus als ik (1/2) en (2/3) heb en ik doe een bewerking, zou het een nieuw nummer moeten retourneren, ook niet wijzigen van de twee die ik heb doorgegeven. In dat geval staat je controle altijd in de constructor voor een nul, maar je moet uitleggen welke bewerking tot deze fout heeft geleid.


Antwoord 2, autoriteit 100%

En wat zou een goede manier zijn om de noemer van 0 te verbieden? Uitzondering weggooien of forceren om gelijk te zijn aan 1?

Dat is helemaal een stijlvraag, zonder aantoonbaar correct antwoord…

Maar… Ik zou met een uitzondering gaan. Nogmaals, dit is gewoon stijl. Het stilzwijgend wijzigen van de waarde zou stilzwijgend doorgaan nadat u iets anders heeft gedaan dan waar de beller om vroeg.

Een ander alternatief zou zijn om de noemer 0 toe te staan, maar een manier te hebben om de gebruiker te informeren dat de huidige algemene waarde, a/b, NaN of oneindig is, of welke “speciale waarde” u ook wilt definiëren.

Doceer het in ieder geval zorgvuldig, zodat een gebruiker van de klas weloverwogen keuzes kan maken.


Antwoord 3, autoriteit 100%

Je breukconstructor moet een teller en een noemer als parameters hebben (of een geheel getal). Het hele probleem kan eenvoudig worden opgelost door overbelasting van de operator.

En ja, de beste manier om mislukte constructors aan te pakken is via uitzonderingen. Vergeet niet dezelfde division_by_zero-uitzondering te gebruiken als je twee breuken deelt en de teller van de noemer nul is.


Antwoord 4, autoriteit 50%

Uw methoden kunnen zijn (ervan uitgaande dat uw klasse “Fraction” heet):

Fraction Fraction::sum(Fraction &otherFraction)
Fraction Fraction::difference(Fraction &otherFraction)
Fraction Fraction::product(Fraction &otherFraction)
Fraction Fraction::division(Fraction &otherFraction)

(Gebruik de methodenamen die je hebt beschreven – ik zou voor iets anders kunnen gaan)

Elk van deze zou een nieuw Fractionobject retourneren dat het resultaat bevat.

Je zou graag bonuspunten gebruiken voor het gebruik van overbelasting door operators en het opnieuw definiëren van wat + - / *betekende.


Antwoord 5, autoriteit 50%

Zoveel vragen in één vraag! Laat me er één (paar) voor je beantwoorden:

Waarom toont boek breuk?
gelijkwaardigheid? Wat moet ik doen
daarmee?

Overweeg dit gebruik van uw klasse Fraction:

TEST(FractionsAreEquivalent)
{
    const Fraction one_over_two(1, 2); // 0.5
    const Fraction two_over_four(2, 4); // 0.5
    const bool equivalent = (one_over_two == two_over_four);
    CHECK(equivalent);
}

Dit gebruikt bool Fraction::operator ==(const Fraction& rhs) const.


Antwoord 6

Ik ben een nieuweling, dus het spijt me als mijn code er zo noob uitziet 😛

   #include<iostream>
    using namespace std;
    class Fraction
    {
    private :
    int x;//NUMERATOR
    int y;//DENOMINATOR
    public :    
    Fraction(int tx = 0, int ty = 1)
    {
    if(ty == 0)
    { 
    x = 0; 
    y = 1;
    exit(0);                        
    }else
    {
    x = tx;
    y = ty;
    }
    }
    void simplify()
    {
    for(int i = x; i >1;i--)
    {
    if(x%i == 0 && y%i == 0)
    {   
    x = x/i;
    y = y/i;
    } 
    }
    }
    void Input()
    {
    cout<<"Input NUMERATOR: ";
    cin>>x;
    cout<<"Input DENOMINATOR: ";
    cin>>y; 
    if(y==0)
    {
    cout<<"ERROR";
    exit(0);    
    }   
    }
    void Display()
    {
    cout<< x << "/" << y <<endl;
    }
    Fraction operator + (Fraction f){
    Fraction temp;
    temp.x = x * f.y + y * f.x;
    temp.y = y * f.y;
    return temp; 
    }
    Fraction operator - (Fraction f){
    Fraction temp;
    temp.x = x * f.y - y * f.x;
    temp.y = y * f.y;
    return temp; 
    }
    Fraction operator * (Fraction f){
    Fraction temp;
    temp.x = x * f.x ;
    temp.y = y * f.y;
    return temp; 
    }
    Fraction operator / (Fraction f){
    Fraction temp;
    temp.x = x * f.y ;
    temp.y = y * f.x;
    return temp; 
    }
    };
    int main ()
    {   
    Fraction f1;
    f1.Input();
    cout<<"Fraction: ";
    f1.simplify();
    f1.Display();
    Fraction f2;    
    f2.Input();
    cout<<"Fraction: ";
    f2.simplify();
    f2.Display();
    Fraction f3,f4,f5,f6;
    f3 = f1 + f2;
    f4 = f1 - f2;
    f5 = f1 * f2;   
    f6 = f1 / f2;
    cout<<"Sum"<<endl;
    f3.simplify();
    f3.Display();
    cout<<"Difference"<<endl;
    f4.simplify();
    f4.Display();
    cout<<"Product"<<endl;
    f5.simplify();
    f5.Display();
    cout<<"Division"<<endl;
    f6.simplify();
    f6.Display();           
    return 0;
    }

Blokquote


Antwoord 7

Ik heb een versie van deze Fractions-klasse gemaakt en hoewel mijn codering verschrikkelijk is, zou het moeten werken. Merk op dat ik de operator <=>heb gedefinieerd, die is geïntroduceerd in C++20, en definieert <, >, <=, >=automatisch. Als je dat niet hebt, kun je std::rel_opsgebruiken of ze allemaal een voor een definiëren.

Fractie.h:

#include <memory>
#include <numeric>
#include <string>
class Fraction
{
private: 
    long long num{ 1 };
    long long denom{ 1 };
    inline void simplify() {
        auto gcd{ std::make_unique<long long>(std::gcd(num, denom)) };
        num /= *gcd;
        denom /= *gcd;
        gcd.reset();
        if (denom < 0) {
            num = -num;
            denom = -denom;
        }
    }
public:
    Fraction(double numerator = 1, double denominator = 1);
    Fraction(double numerator, double denominator, int integer_part);
    Fraction(const Fraction& f);
    long long numerator() const;
    long long denominator() const;
    auto setnumerator(long long nv);
    auto setdenominator(long long nv);
    double value() const;
    Fraction reciprocal() const;
    std::string str(size_t mode = 0) const;
    bool operator==(const Fraction& f) const;
    auto operator<=>(const Fraction& f) const;
    bool operator==(size_t s) const;
    auto operator<=>(size_t s) const;
    friend bool operator== (size_t s, Fraction& f);
    friend auto operator<=> (size_t s, Fraction& f);
    bool operator==(double d) const;
    auto operator<=>(double d) const;
    friend bool operator== (double d, Fraction& f);
    friend auto operator<=> (double d, Fraction& f);
    Fraction operator+(const Fraction& f) const;
    Fraction operator+(size_t s) const;
    Fraction operator+(double d) const;
    friend Fraction operator+(size_t s, const Fraction& f);
    friend Fraction operator+(double d, const Fraction& f);
    Fraction operator-(const Fraction& f) const;
    Fraction operator-(size_t s) const;
    Fraction operator-(double d) const;
    friend Fraction operator-(size_t s, const Fraction& f);
    friend Fraction operator-(double d, const Fraction& f);
    Fraction operator*(const Fraction& f) const;
    Fraction operator*(size_t s) const;
    Fraction operator*(double d) const;
    friend Fraction operator*(size_t s, const Fraction& f);
    friend Fraction operator*(double d, const Fraction& f);
    Fraction operator/(const Fraction& f) const;
    Fraction operator/(size_t s) const;
    Fraction operator/(double d) const;
    friend Fraction operator/(size_t s, const Fraction& f);
    friend Fraction operator/(double d, const Fraction& f);
    Fraction operator%(const Fraction& f) const;
    Fraction operator%(size_t s) const;
    Fraction operator%(double d) const;
    friend size_t operator%(size_t s, const Fraction& f);
    friend double operator%(double d, const Fraction& f);
    Fraction& operator+=(const Fraction& f);
    Fraction& operator+=(size_t s);
    Fraction& operator+=(double d);
    friend size_t operator+=(size_t s, Fraction& f);
    friend double operator+=(double d, Fraction& f);
    Fraction& operator-=(const Fraction& f);
    Fraction& operator-=(size_t s);
    Fraction& operator-=(double d);
    friend size_t operator-=(size_t s, Fraction& f);
    friend double operator-=(double d, Fraction& f);
    Fraction& operator*=(const Fraction& f);
    Fraction& operator*=(size_t s);
    Fraction& operator*=(double d);
    friend size_t operator*=(size_t s, Fraction& f);
    friend double operator*=(double d, Fraction& f);
    Fraction& operator/=(const Fraction& f);
    Fraction& operator/=(size_t s);
    Fraction& operator/=(double d);
    friend size_t operator/=(size_t s, Fraction& f);
    friend double operator/=(double d, Fraction& f);
    Fraction& operator%=(const Fraction& f);
    Fraction& operator%=(size_t s);
    Fraction& operator%=(double d);
    friend size_t operator%=(size_t s, Fraction& f);
    friend double operator%=(double d, Fraction& f);
    Fraction& operator++();
    Fraction operator++(int);
    Fraction& operator--();
    Fraction operator--(int);
    Fraction operator+();
    Fraction operator-();
    long long operator[](int i);
};

Fractie.cpp:

#include "Fraction.h"
#include <limits>
#include <sstream>
Fraction::Fraction(double numerator, double denominator)
{
    double tsn{ numerator }, tsd{ denominator };
    while ((static_cast<long long>(tsn) != tsn || static_cast<long long>(tsd) != tsd) && std::numeric_limits<long long>::max() / 10 > tsn && std::numeric_limits<long long>::max() / 10 > tsd) {
        tsn *= 10;
        tsd *= 10;
    }
    num = tsn;
    denom = tsd;
    simplify();
}
Fraction::Fraction(double numerator, double denominator, int integer_part)
{
    numerator += denominator * integer_part;
    double tsn{ numerator }, tsd{ denominator };
    while ((static_cast<long long>(tsn) != tsn || static_cast<long long>(tsd) != tsd) && std::numeric_limits<long long>::max() / 10 > tsn && std::numeric_limits<long long>::max() / 10 > tsd) {
        tsn *= 10;
        tsd *= 10;
    }
    num = tsn;
    denom = tsd;
    simplify();
}
Fraction::Fraction(const Fraction& f)
{
    num = f.numerator();
    denom = f.denominator();
}
long long Fraction::numerator() const
{
    return num;
}
long long Fraction::denominator() const
{
    return denom;
}
auto Fraction::setnumerator(long long nv)
{
    num = nv;
    simplify();
    return this;
}
auto Fraction::setdenominator(long long nv)
{
    denom = nv;
    simplify();
    return this;
}
double Fraction::value() const
{
    return static_cast<double>(num) / denom;
}
Fraction Fraction::reciprocal() const
{
    return Fraction(denom, num);
}
std::string Fraction::str(size_t mode) const 
{
    std::stringstream ss;
    if (mode == 0) {
        ss << num;
        if (denom != 1) {
            ss << '/' << denom;
        }
    }
    else {
        if (num % denom == 0 || denom == 1) {
            ss << num / denom;
        }
        else {
            if (abs(denom) > abs(num)) {
                ss << num << '/' << denom;
            }
            else if (num < 0) {
                ss << '-' << '(' << (num / denom) << ' ' << -(num % denom) << '/' << denom << ')';
            }
            else {
                ss << (num / denom) << ' ' << num % denom << '/' << denom;
            }
        }
    }
    return ss.str();
}
bool Fraction::operator==(const Fraction& f) const
{
    return value() == f.value();
}
auto Fraction::operator<=>(const Fraction& f) const 
{
    return value() <=> f.value();
}
bool Fraction::operator==(size_t s) const 
{
    return value() == s;
}
auto Fraction::operator<=>(size_t s) const 
{
    return value() <=> s;
}
bool operator==(size_t s, const Fraction& f)
{
    return s == f.value();
}
auto operator<=>(size_t s, const Fraction& f)
{
    return s <=> f.value();
}
bool Fraction::operator==(double d) const
{
    return value() == d;
}
auto Fraction::operator<=>(double d) const
{
    return value() <=> d;
}
bool operator==(double d, Fraction& f)
{
    return f.value() == d;
}
auto operator<=>(double d, Fraction& f)
{
    return f.value() <=> d;
}
Fraction Fraction::operator+(const Fraction& f) const
{
    return Fraction(num * f.denominator() + f.numerator() * denom, denom * f.denominator());
}
Fraction Fraction::operator+(size_t s) const
{
    return Fraction(s * denom + num, denom);
}
Fraction Fraction::operator+(double d) const
{
    return *this + Fraction(d);
}
Fraction operator+(size_t s, const Fraction& f)
{
    return f + s;
}
Fraction operator+(double d, const Fraction& f)
{
    return f + d;
}
Fraction Fraction::operator-(const Fraction& f) const
{
    return Fraction(num * f.denominator() - f.numerator() * denom, denom * f.denominator());
}
Fraction Fraction::operator-(size_t s) const
{
    return Fraction(num - (s * denom), denom);
}
Fraction Fraction::operator-(double d) const
{
    return *this - Fraction(d);
}
Fraction operator-(size_t s, const Fraction& f)
{
    return Fraction(s * f.denom - f.num, f.denom);
}
Fraction operator-(double d, const Fraction& f)
{
    return Fraction(d) - f;
}
Fraction Fraction::operator*(const Fraction& f) const
{
    return Fraction(num * f.numerator(), denom * f.denominator());
}
Fraction Fraction::operator*(size_t s) const
{
    return Fraction(num * s, denom);
}
Fraction Fraction::operator*(double d) const
{
    return Fraction(num * d, denom);
}
Fraction operator*(size_t s, const Fraction& f)
{
    return Fraction(f.numerator() * s, f.denominator());
}
Fraction operator*(double d, const Fraction& f)
{
    return Fraction(f.numerator() * d, f.denominator());
}
Fraction Fraction::operator/(const Fraction& f) const
{
    return (*this) * f.reciprocal();
}
Fraction Fraction::operator/(size_t s) const
{
    return Fraction(num, denom * s);
}
Fraction Fraction::operator/(double d) const
{
    return Fraction(num, denom * d);
}
Fraction operator/(size_t s, const Fraction& f)
{
    return s * f.reciprocal();
}
Fraction operator/(double d, const Fraction& f)
{
    return d * f.reciprocal();
}
Fraction Fraction::operator%(const Fraction& f) const
{
    return ((*this) / f).value() > 0 ? Fraction((*this) - (floor(((*this) / f).value()) * f)) : Fraction((*this) - (ceil(((*this) / f).value()) * f));
}
Fraction Fraction::operator%(size_t s) const
{
    return ((*this) / s).value() > 0 ? Fraction((*this) - (floor(((*this) / s).value()) * s)) : Fraction((*this) - (ceil(((*this) / s).value()) * s));
}
Fraction Fraction::operator%(double d) const
{
    return ((*this) / d).value() > 0 ? Fraction((*this) - (floor(((*this) / d).value()) * d)) : Fraction((*this) - (ceil(((*this) / d).value()) * d));
}
size_t operator%(size_t s, const Fraction& f)
{
    return (f / s).value() > 0 ? ((f) - (floor((s / f).value()) * f)).value() : ((f)-(ceil((s / f).value()) * f)).value();
}
double operator%(double d, const Fraction& f)
{
    return (f / d).value() > 0 ? ((f)-(floor((d / f).value()) * f)).value() : ((f)-(ceil((d / f).value()) * f)).value();
}
Fraction& Fraction::operator+=(const Fraction& f)
{
    *this = *this + f;
    return *this;
}
Fraction& Fraction::operator+=(size_t s)
{
    *this = *this + s;
    return *this;
}
Fraction& Fraction::operator+=(double d)
{
    *this = *this + d;
    return *this;
}
size_t operator+=(size_t s, Fraction& f)
{
    s += round(f.value());
    return s;
}
double operator+=(double d, Fraction& f)
{
    d += f.value();
    return d;
}
Fraction& Fraction::operator-=(const Fraction& f)
{
    *this = *this - f;
    return *this;
}
Fraction& Fraction::operator-=(size_t s)
{
    *this = *this - s;
    return *this;
}
Fraction& Fraction::operator-=(double d)
{
    *this = *this - d;
    return *this;
}
size_t operator-=(size_t s, Fraction& f)
{
    s -= round(f.value());
    return s;
}
double operator-=(double d, Fraction& f)
{
    d -= f.value();
    return d;
}
Fraction& Fraction::operator*=(const Fraction& f)
{
    *this = *this * f;
    return *this;
}
Fraction& Fraction::operator*=(size_t s)
{
    *this = *this * s;
    return *this;
}
Fraction& Fraction::operator*=(double d)
{
    *this = *this * d;
    return *this;
}
size_t operator*=(size_t s, Fraction& f)
{
    s *= round(f.value());
    return s;
}
double operator*=(double d, Fraction& f)
{
    d *= f.value();
    return d;
}
Fraction& Fraction::operator/=(const Fraction& f)
{
    *this = *this / f;
    return *this;
}
Fraction& Fraction::operator/=(size_t s)
{
    *this = *this / s;
    return *this;
}
Fraction& Fraction::operator/=(double d)
{
    *this = *this / d;
    return *this;
}
size_t operator/=(size_t s, Fraction& f)
{
    s /= round(f.value());
    return s;
}
double operator/=(double d, Fraction& f)
{
    d /= f.value();
    return d;
}
Fraction& Fraction::operator%=(const Fraction& f)
{
    *this = *this % f;
    return *this;
}
Fraction& Fraction::operator%=(size_t s)
{
    *this = *this % s;
    return *this;
}
Fraction& Fraction::operator%=(double d)
{
    *this = *this % d;
    return *this;
}
size_t operator%=(size_t s, Fraction& f)
{
    s = s % f;
    return s;
}
double operator%=(double d, Fraction& f)
{
    d = d % f;
    return d;
}
Fraction& Fraction::operator++()
{
    this->num += this->denom;
    return *this;
}
Fraction Fraction::operator++(int)
{
    Fraction copy{ *this };
    this->num += this->denom;
    return copy;
}
Fraction& Fraction::operator--()
{
    this->num -= this->denom;
    return *this;
}
Fraction Fraction::operator--(int)
{
    Fraction copy{ *this };
    this->num -= this->denom;
    return copy;
}
Fraction Fraction::operator+()
{
    return *this;
}
Fraction Fraction::operator-()
{
    return Fraction(-num, denom);
}
long long Fraction::operator[](int i)
{
    return i == 0 ? num : denom;
}

De meeste van de onderste zijn gewoon overbelasting van verschillende soorten operators, omdat ik de operators wilde gebruiken voor Fraction-objecten, size_t en dubbele objecten. Dit zou meer moeten worden geoptimaliseerd omdat het een functie vereenvoudigt () heeft die wordt gebruikt en in plaats van functies zoals som en verschil, heb ik overbelasting van de operator gebruikt. Fraction.str() is iets meer geoptimaliseerd dan hierboven. Wat betreft de nuldeling, ik denk dat het zal worden gepakt en de compiler zal op zijn minst een waarschuwing afgeven en tijdens het uitvoeren zou het een drijvende-kommafout moeten geven. Als je bugs in de code hebt gevonden, reageer dan hieronder!

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes