【问题标题】:How to output fraction instead of decimal number?如何输出分数而不是十进制数?
【发布时间】:2011-06-16 16:28:10
【问题描述】:

在 C++ 中,当我计算 2/3 时,它会输出十进制值,我怎样才能得到原始格式(即 2/3)而不是 0.66666667

谢谢

【问题讨论】:

  • 这取决于你所说的“计算 2/3”是什么意思
  • 这个问题应该附带一个代码示例以及实际和预期的输出。
  • 这里有一个有趣的演示,展示了将小数转换为分数的工作原理:webmath.com/dec2fract.html
  • @Tony:是的,这很有趣,但在数学上远非严格,所以我觉得它对于真正理解这个主题具有危险的误导性。这是一个开始:-)。有关更详尽的解释,请参见例如en.wikipedia.org/wiki/Continued_fractions ,特别是“区间内的最佳理性”部分。 (对不起,我是数学家,忍不住……)。
  • 让我想起了355/113

标签: c++ fractions


【解决方案1】:

使用最大公约数概念。

如果我们将数字除以它们的数字的 gcd,我们会得到这些数字的最小可能值。示例:-

#define si long long
int main() {
si int total=4;
si int count=2;
si int g= __gcd(count,total);
count/=g;
total/=g;
cout<<count<<"/"<<total<<endl;
}
for more reference check out this:-https://www.codechef.com/viewsolution/17873537

【讨论】:

    【解决方案2】:
    #include <iostream>
    using namespace std;
    
    int main() {
        int a,b,q,r;
        cin>>a>>b;//first number and second number
        q = a/b;
        r = a-q*b;
        cout<<q<<" "<<r<<" "<<"/"<<" "<<b<<"\n";
        return 0;
    }
    

    我刚刚得到了 a/b 的商,然后得到了 a-q*b 的余数。 如有建议,请开放。

    【讨论】:

      【解决方案3】:

      这是一个将十进制数转换为分数的程序

      #include<iostream>
      using namespace std;
      
      int main()
      {
      
          float num, origNum, rem = 1;
          int den = 1, i, count=0, gcd=1;
      
          cout << "Enter any float number to convert it into mixed fraction: ";
          cin >> origNum;
      
          num = origNum - static_cast<int>(origNum);
      
          if (num > 0.1)
          {
              while ( (rem > 0.1) )
              {
                  num = num * 10;
                  rem = num - static_cast<int>(num);
                  count++;
              }
      
              for (i = 1; i <= count; i++) // counter is for the calculation of denominator part of mixed fraction 
              {
                  den = den * 10;
              }
      
              for (i = 2; i <= num|| i<=rem; i++)
              {
                  if( (static_cast<int>(num) % i == 0) && (den % i == 0) )
                  {
                      gcd = i;
                  }   
              }
      
              cout << (static_cast<int>(origNum)) << " and " << (static_cast<int>(num))/gcd << "/" << den/gcd;
          }
          else
              cout << (static_cast<int>(origNum));
      
          return 0;   
      }
      

      【讨论】:

        【解决方案4】:

        将这两个数字除以他们的 HCF 可能会有所帮助。

        【讨论】:

          【解决方案5】:

          我是初学者,我使用的这种方式可能不是正确的方式

          #include <iostream>
          
          using namespace std;
          int main ()
          {
            double a;
            double b;
            double c;
          
            cout << "first number: ";
            cin >> a;
            cout << "second number: ";
            cin >> b;
          
            c = a/b;
            cout << "result is: " << c << endl;
          
            if (b != 0) {
              if (a > 0) {
                if (c - (int)c > 0 && c - (int)c < 1)
                  cout << "fraction: " << a << "/" << b;
              } else {
                if (c - (int)c < 0 && c - (int)c < 1)
                  cout << "fraction: " << a << "/" << b;
              }
            }
          
            return 0;
          }
          

          【讨论】:

          • 我想你回答了一个不同的问题。您的答案是将浮点数的整数部分与非整数部分分开(即将1.25 分成1.25)。但问题是关于将浮点数转换为有理数的分数表示,即1 1/45/4
          • 有了这个你可以识别浮动结果并以分数方式打印它们
          • 对于1.25,您的程序输出1.25,对吗?它如何将.25 转换为1/4
          • 好吧,伙计们,我只是按照我所说的方式编辑了它:)检查并发表评论:)
          • 但是现在你的程序要求用户明确地填写ab。其他一些答案也这么说;如果输入有理数,您可以简单地存储它,以便在需要时使用它。但真正的困难在于从浮点数计算ab
          【解决方案6】:

          为了简化工作,我建议您尽可能使用已知分母。

          我正在使用一个应用程序,其中分数被限制为 2 的分母或使用 3(三分之二)。

          我使用近似值转换为这些分数(四舍五入到最接近的 1.0/24.0)。

          如果没有一些限制,找到分母可能会很麻烦,并且会占用大量执行时间。

          【讨论】:

            【解决方案7】:

            编写自己的 Rational 类来计算除法

            class Rational
            {
            public:
                int numerator, denominator;
            
                Rational(int num, int den=1){
                    numerator = num;
                    denominator=den;
                }
                Rational(Rational other){
                    numerator = other.numerator;
                    denominator = other.denominator;
                }
                double operator / (int divisor){
                        denominator *= divisor;
                        simplificate();
                        return getrealformat();
                }
                Rational& operator / (int divisor){
                        denominator *= divisor;
                        simplificate();
                        return this;
                }
                Rational& operator / (Rational &divisor){
                        numerator *= divisor.numerator;
                        denominator *= divisor.denominator;
                        simplificate();
                        return this;
                }
                double operator / (int divisor){
                        denominator *= divisor;
                        simplificate();
                    return getrealformat();
                }
                double getrealformat(){
                    return numerator/denominator;
                }
                simplificate(){
                    int commondivisor = 1;
                    for(int i=2;i<=min(abs(numerator), abs(denominator));i++)
                        if( numerator%i == 0 && denominator%i == 0 )
                            commondivisor = i;
                    numerator /= commondivisor;
                    denominator /= commondivisor;
                }
            };
            

            使用

            Rational r1(45), r2(90), r3=r1/r2;
            cout<<r3.numerator<<'/'<<r3.denominator;
            cout<<r3.getrealformat();
            

            【讨论】:

            • 如何处理从floatdoubleRational 的转换?
            • Rational operator=(double number){ numerator = number*decimals;/*之前指定过一次,例如。 100 */ 分母 = 小数;简化(); }
            • pastebin.com/LhGK3gNG :在这里我尝试测试上述类。但是,我不能按原样使用上面的代码(因为它显示了一些错误),我不得不重写一些东西。最后它没有按预期工作。任何人都可以检查出了什么问题吗? @ThomasMatthews
            • 感谢您的链接,但防火墙正在阻止访问该链接。也许你可以编辑你的帖子?
            • @ThomasMatthews 我创建了新链接:paste.ofcode.org/SVZLDr72BUyEUkam5GrAEt希望这会起作用
            【解决方案8】:

            如果我理解正确,您有一个浮点数(floatdouble 类型变量),并且您希望将此值输出为分数。

            如果是这种情况,您需要进一步说明您的问题:

            • FP 数分数,根据定义:FP 数由两个整数组成,尾数 m 和指数 e (和一个标志,但这在这里无关紧要)。所以每个FP数实际上是一对(m,e),它所代表的值ff=mb^e(其中b 是固定整数基数,通常为 2)。因此,作为分数的自然表示只是 m / b^(-e)e (如果 e>=0 ,f 无论如何都是不可或缺的)。
            • 但是,您可能希望获得具有最小合理除数的分数。这是一个不同的问题。要得到是,你可以例如使用 Pari/GP 库中的 bestappr 函数。在您的情况下,您可能会使用bestappr(x, A),其中 x 是您的输入,而 A 是您想要尝试的最大分母。 bestappr 将为您提供最接近 x 且分母仍小于 A 的分数。

            【讨论】:

              【解决方案9】:

              您必须将它们存储在某种带有两个整数字段的 Fraction 类中。当然,您必须先化简分数,然后再将其用于输出。

              您可以开发自己的类或使用一些库,例如用于精确数学的库:CLN - Class Library for Numbers

              【讨论】:

              • 具有两个整数字段的类:提名者和分母对于将floatdouble 转换为分数没有帮助。 Fraction 类可以转换为分数。
              • 托马斯,我不明白。但是,在某种程度上,floatdouble 也是分数。据我了解,问题是关于如何从一开始就管理问题,解决方案是首先避免创建floatdouble 变量。
              【解决方案10】:

              您可以将所有分数的分子和分母存储为整数。整数在二进制中具有精确的表示。

              【讨论】:

              • ...直到他们没有。有一个最大 int,超过它你必须使用某种 bignum 库。或者浮点数,这让他回到了原来的问题。
              • @T.E.D.,整数溢出不是 OP 的问题。
              • 我想说 1/10^20 对于几乎任何应用程序来说都足够了。
              【解决方案11】:

              我怎样才能得到原始格式 (即 2/3)而不是 0.66666667

              只有通过使用自定义输出运算符包装 GMP 库之类的东西非常困难。下面是关于 GMP 的更多内容:

              什么是GMP?

              GMP 是一个免费的库 任意精度算术, 对有符号整数进行运算,有理数 数字和浮点数。 没有实际限制 精度,除了那些隐含的 机器中的可用内存 GMP 继续运行。 GMP有丰富的一套 函数,并且函数有一个 常规界面。

              GMP的主要目标应用 是密码学应用程序和 研究,互联网安全 应用程序,代数系统, 计算代数研究等

              GMP 是经过精心设计的 尽可能快,无论是小 操作数和巨大的操作数。这 速度是通过使用全词来实现的 作为基本算术类型,通过使用 快速算法,高度优化 最常见的汇编代码 许多 CPU 的内部循环,并且通过 普遍强调速度。

              GMP 比任何其他 bignum 都快 图书馆。 GMP的优势 随着操作数大小的增加 许多操作,因为 GMP 使用 渐近更快的算法。

              第一个 GMP 版本是在 1991. 它不断开发和维护,新版本大约 一年一次。

              【讨论】:

              • 这个或类似的设施几乎是唯一的方法。您仍然必须从一开始就跟踪。如果你只有 0.6666667,你无法知道是 6666667/10000000 还是 2/3。
              【解决方案12】:

              你不能。您需要编写一个专门用于保存有理数(即分数)的类。或者只是使用Boost Rational Number library

              【讨论】:

              • +1:显而易见的解决方案 - 确实不要丢弃这些信息!
              • 产生0.66666667int 值的数量是有限的。为什么不写一个选择一个的函数呢?答案不是“你不能”
              • @Inverse:你不能用任何合理的方法。听起来您建议将浮点值乘以所有可能的分母,直到找到接近整数值的结果?显然,这本质上具有无限的算法复杂性(有更好的方法吗?)。即使这样也不会按照 OP 的要求恢复“原始格式”;它无法区分 2/3 和 4/6。
              • @Inverse: 不,有无数个整数可以产生0.66666667。它可能是 1/3,或 1000000/3000001,或 1000001/3000000 等(假设有足够的零来耗尽 FP 精度)。您可以很容易地证明,对于任何 FP 数,都有无限(尽管可数无限)个整数分数。
              • 当然,在实践中,您通常希望分母最小的分数与您的 FP 数相当接近。如果您为 FP 数和分数之间的最大差异设置了一个固定限制(或者如果您为分母设置了一个上限),那么确实只有一个这样的分数。有关详细信息,请参阅我的答案:-)。
              【解决方案13】:

              这通常是不可能的:浮点数不精确,并且没有保留足够的信息来完全重建分数。

              但是,您可以编写一个启发式地找到“最佳”近似值的函数,其中分子和分母较小的分数是首选,与浮点数具有几乎相同值的分数也是如此。

              如果您完全控制代码,Oli 的想法会更好:首先不要丢弃信息。

              【讨论】:

              • 这不是真的。如果你有一个你愿意接受的特定精度(比如 0.00001),你可以乘以该精度的倒数——这会给你一个很大的分子和分母。那时可以对分子和分母进行因式分解,然后开始去除公因子,直到剩下的最小分数在您指定的原始浮点数的精度范围内。
              • 您的意思是:对于所有浮点数而言,这并不总是正确的。更准确地说:对于任何浮点数,有无数个有理数至少与其他浮点数一样接近,尽管其中一个有理数恰好等于浮点数。这样更好吗?
              • @BobG:该算法通常不会找到“最佳”分数,因为精心挑选的初始分母(在您的示例中为 1/0.00001)不能被最佳除数(例如“3”在肖恩的例子中)。无论如何,这听起来像是一个不同的问题......
              • 无论如何,实现寻找最佳有理逼近的算法是不必要的;此类实现已经存在,例如在 Pari/GP 中(请参阅我的回答)。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-09-05
              • 2020-03-07
              • 1970-01-01
              • 2014-01-06
              • 1970-01-01
              相关资源
              最近更新 更多