【问题标题】:Convert Fraction to decimal number and sort them将分数转换为十进制数并对它们进行排序
【发布时间】:2020-06-24 06:53:40
【问题描述】:

我想将有理数按升序排序,因此我尝试将数字转换为十进制并对它们进行排序。我已经完成了转换为小数的部分,但我不知道如何在这部分之后继续对小数进行排序。

例如:1/3、5/3、7/2、1/2
输出:1/2、1/3、5/3、7/2

#include<iostream>
#include<string>

using namespace std;

class Fraction
{
private:
    float numer = 0.0f;
    float denom = 0.0f;

public:
    Fraction(int numer, int denom);
    ~Fraction();
    void setNum(int NumInput) 
    { 
        numer = NumInput; 
    };
    int getNum() 
    { 
        return numer; 
    };
    void setDem(int DemInput) 
    { 
        denom = DemInput; 
    };
    int getDem() 
    { 
        return denom; 
    };

    float getDec()
    {
        return numer / denom;
    };
};

Fraction::Fraction(int numerator, int denominator)
{
    numer = numerator;
    denom = denominator;
}

Fraction::~Fraction()
{

}

int main(int argc, const char* argv[])
{
    Fraction a1(2, 3);
    Fraction a2(7, 2);
    Fraction a3(6, 7);
    Fraction a4(27, 4);
}

【问题讨论】:

  • 您可能可以编写自己的排序算法,或者尝试使用 std::sort(在算法标题下)和自定义函数进行比较。这里有一个如何实现的示例:en.cppreference.com/w/cpp/algorithm/sort
  • 你可以为你的类Fraction定义&lt;操作符,直接使用std::sort。附带一点:为什么您使用float 而不是int 作为分子和分母?

标签: c++ sorting


【解决方案1】:

无需转换为十进制即可比较两个分数。如果您有 a/b 和 c/d,那么只需比较 a*db*c

bool operator<(const Fraction& left, const Fraction& right)
{
    return (double)left.getNum()*right.getDem < (double)left.getDem()*right.getNum();
}

这比比较十进制值更正确,因为它避免了除以 2 个数字后的四舍五入。此外它也更快,因为乘法比除法快得多。一旦有了比较功能或operator&lt;,您就可以使用std::sort() 对它们进行排序。还要将get 函数设为const,这样编译器就不会像stefan 所说的那样每次调用它时重新评估这些值

请注意,最好将分子和分母定义为 整数 而不是上面评论的浮点数,因为浮点类型实际上是引擎盖下的分数,尽管分母的范围更受限制

您还需要符号规范化来完成这项工作。对于负分数,您可以选择始终将分子或分母设置为负数。或者,您可以在像这样比较它们时进行标准化

int dem = (long long)left.getNum()*right.getDem - left.getDem()*right.getNum();
if (right.getDem() < 0) dem = -dem;
if (left.getDem() < 0) dem = -dem;
return (dem > 0) - (dem < 0);

【讨论】:

  • 正确的方法有效。附注:为什么不使用 friend 运算符来直接访问私人号码?没有风险,因为变量被声明为常量
  • @Damien 是的,您甚至可以创建一个公共会员操作员。我只是从 stefan 的答案中复制了定义,而不是重新输入
【解决方案2】:

首先,让你的 getXXX 函数保持不变,然后像这样实现一个比较运算符

bool operator<(const Fraction& left, const Fraction& right)
{
    return left.getDec() < right.getDec();
}

然后按照上面的建议对分数集合使用 std::sort()。

您必须更改 getDec() 函数以防止被零除。

【讨论】:

    【解决方案3】:

    首先,我想指出,在将有理分数转换为小数时,由于您使用的数据类型的大小限制,会降低准确性。

    例如,如果小数点后的前 15 位相同,那么您的程序将无法找到这两个数字中的较大者,因此无法对它们进行排序。

    例子:

    111 111 111 111 111 3 / 1 000 000 000 000 000 0

    111 111 111 111 111 7 / 1 000 000 000 000 000 0

    我会推荐一种不同的方法

    1. 将分子和分母都作为long/最大可能的整数类型。

    2. 找出所有分母的 LCM。

    3. 将每个分子乘以(LCM / 相应分母)。

    4. 根据分子对分数进行排序。

    【讨论】:

    • 注意: phuclv 的方法比我的更有效。
    猜你喜欢
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 2013-05-31
    • 2018-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多