将小数转换为小数c ++

时间:2014-10-30 01:46:21

标签: c++ algorithm

我可以使用什么算法将十进制数转换并输入到c ++中的分数形式。例如,如果我输入1.25,我希望转换为输出为1 1/4。

4 个答案:

答案 0 :(得分:6)

首先得到小数部分,然后取gcd。使用欧几里德算法http://en.wikipedia.org/wiki/Euclidean_algorithm

void foo(double input)
{
    double integral = std::floor(input);
    double frac = input - integral;

    const long precision = 1000000000; // This is the accuracy.

    long gcd_ = gcd(round(frac * precision), precision);

    long denominator = precision / gcd_;
    long numerator = round(frac * precision) / gcd_;

    std::cout << integral << " + ";
    std::cout << numerator << " / " << denominator << std::endl;
}

long gcd(long a, long b)
{
    if (a == 0)
        return b;
    else if (b == 0)
        return a;

    if (a < b)
        return gcd(a, b % a);
    else
        return gcd(b, a % b);
}

答案 1 :(得分:4)

#include <iostream>
#include <valarray> 

using namespace std;

void as_fraction(double number, int cycles = 10, double precision = 5e-4){
    int sign  = number > 0 ? 1 : -1;
    number = number * sign; //abs(number);
    double new_number,whole_part;
    double decimal_part =  number - (int)number;
    int counter = 0;
    
    valarray<double> vec_1{double((int) number), 1}, vec_2{1,0}, temporary;
    
    while(decimal_part > precision & counter < cycles){
        new_number = 1 / decimal_part;
        whole_part = (int) new_number;
        
        temporary = vec_1;
        vec_1 = whole_part * vec_1 + vec_2;
        vec_2 = temporary;
        
        decimal_part = new_number - whole_part;
        counter += 1;
    }
    cout<<"x: "<< number <<"\tFraction: " << sign * vec_1[0]<<'/'<< vec_1[1]<<endl;
}

int main()
{
    as_fraction(3.142857);
    as_fraction(0.1);
    as_fraction(0.333333);
    as_fraction(514.0/37.0);
    as_fraction(1.17171717);
    as_fraction(-1.17);
}


x: 3.14286      Fraction: 22/7                                                                                                                
x: 0.1          Fraction: 1/10                                                                                                                        
x: 0.333333     Fraction: 1/3                                                                                                                 
x: 13.8919      Fraction: 514/37                                                                                                              
x: 1.17172      Fraction: 116/99                                                                                                              
x: 1.17         Fraction: -117/100

有时候,您可能希望近似十进制数而不需要等价。例如,pi = 3.14159近似为22/7或355/113。我们可以使用cycles参数获取这些信息:

as_fraction(3.14159, 1);
as_fraction(3.14159, 2);
as_fraction(3.14159, 3);

x: 3.14159      Fraction: 22/7                                                                                                                
x: 3.14159      Fraction: 333/106                                                                                                             
x: 3.14159      Fraction: 355/113

答案 2 :(得分:0)

我想出了一个针对这个问题的算法,但我觉得它太冗长了,可以用更少的代码行完成。对于糟糕的缩进感到抱歉很难在溢出时对齐所有内容。

#include <iostream>
using namespace std;


// converts the string half of the inputed decimal number into numerical values void converting
 (string decimalNumber, float&numerator, float& denominator )

 { float number; string valueAfterPoint =decimalNumber.substr(decimalNumber.find("."    ((decimalNumber.length() -1) )); // store the value after the decimal into a valueAfterPoint 

int length = valueAfterPoint.length(); //stores the length of the value after the decimal point into length 

numerator = atof(valueAfterPoint.c_str()); // converts the string type decimal number into a float value and stores it into the numerator

// loop increases the decimal value of the numerator by multiples of ten as long as the length is above zero of the decimal

for (; length > 0; length--)  
    numerator *= 10;

do
 denominator *=10;
  while  (denominator < numerator);



// simplifies the the converted values of the numerator and denominator into simpler values for          an easier to read output 


void simplifying (float& numerator, float& denominator) { int maximumNumber = 9; //Numbers in the tenths place can only range from zero to nine so the maximum number for a position in a position for the decimal number will be nine

bool isDivisble; // is used as a checker to verify whether the value of the numerator has the       found the dividing number that will a value of zero
 // Will check to see if the numerator divided denominator is will equal to zero


   if(int(numerator) % int(denominator) == 0) {
   numerator /= denominator;
   denominator = 1;   
   return; }


  //check to see if the maximum number is greater than the denominator to simplify to lowest     form while (maximumNumber < denominator) { maximumNumber *=10;  }


 // the maximum number loops from nine to zero. This conditions stops if the function isDivisible is true 
 for(; maximumNumber > 0;maximumNumber --){

 isDivisble = ((int(numerator) % maximumNumber == 0) && int(denominator)% maximumNumber == 0);

  if(isDivisble)
 {
    numerator /= maximumNumber;  // when is divisible true numerator be devided by the max        number value for example 25/5 = numerator = 5

   denominator /= maximumNumber; //// when is divisible true denominator be devided by themax        number value for example 100/5 = denominator = 20

 }


 // stop value if numerator and denominator is lower than 17 than it is at the lowest value
 int stop = numerator + denominator;

 if (stop < 17)
 {
     return;
 } } }   

答案 3 :(得分:0)

评论太久了。)

一些评论声称这是不可能的。但是我有相反的意见

我认为正确的解释是可能的,但很容易错误地陈述问题或误解答案。

这里提出的问题是找到给定浮点值的有理逼近。

这肯定是可能的,因为C ++中使用的浮点格式只能存储有理值,通常以符号/尾数/指数的形式存储。以IEEE-754单精度格式为例(为了简化数字),0.333stored as 1499698695241728 * 2^(-52)。这等于其convergents提供increasingly accurate approximations的分数1499698695241728 / 2^52一直到原始值:1/3333/100077590/2330035586813/16777216

这里有两点需要注意。

  • 对于变量float x = 0.333;来说,最佳有理逼近不一定是333 / 1000,因为存储的值并非完全准确,而是{{ 1}},因为浮点数内部表示的精度有限。

  • 一旦分配了浮点值,就不会存储浮点值或源代码是否将其定义为0.3330.333000004291534423828125,因为这两个值都具有{ {3}}内部表示。这就是为什么无法解决(将相关的但不同的)数字的字符串表示形式分为整数部分和小数部分的问题(相关但不同),方法是先转换为浮点,然后在转换后的值。


[ EDIT ]}以下是float x = 0.333;示例的分步详细信息。

  1. float x = 0.333000004;转换为精确分数的代码。
0.333f
  1. the same
float
  1. 这将#include <cfloat> #include <cmath> #include <limits> #include <iostream> #include <iomanip> void flo2frac(float val, unsigned long long* num, unsigned long long* den, int* pwr) { float mul = std::powf(FLT_RADIX, FLT_MANT_DIG); *den = (unsigned long long)mul; *num = (unsigned long long)(std::frexp(val, pwr) * mul); pwr -= FLT_MANT_DIG; } void cout_flo2frac(float val) { unsigned long long num, den; int pwr; flo2frac(val, &num, &den, &pwr); std::cout.precision(std::numeric_limits<float>::max_digits10); std::cout << val << " = " << num << " / " << den << " * " << FLT_RADIX << "^(" << pwr << ")" << std::endl; } int main() { cout_flo2frac(0.333f); } 合理地表示为0.333000004 = 11173626 / 16777216 * 2^(-1)

  2. 剩下要做的是确定精确分数的收敛,这只能使用整数计算来完成。 Output是(由WA提供):

float val = 0.333f;