Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从一个分数中得到分子和分母?_C++ - Fatal编程技术网

C++ 如何从一个分数中得到分子和分母?

C++ 如何从一个分数中得到分子和分母?,c++,C++,如何从一个分数中得到分子和分母?例如,从“1.375”中,我希望得到“1375/1000”或“11/8”。我怎么用C++做? 我试着将点之前和点之后的数字分开,但它没有给出如何获得所需输出的任何想法 > C++中,可以使用Boost Rational类。但你需要给出分子和分母 为此,您需要找出输入字符串中小数点后的数字。您可以通过字符串操纵函数来实现这一点。逐个字符读取输入的字符,并在后找不到任何字符 char inputstr[30]; int noint=0, nodec=0; char

如何从一个分数中得到分子和分母?例如,从“1.375”中,我希望得到“1375/1000”或“11/8”。我怎么用C++做?
我试着将点之前和点之后的数字分开,但它没有给出如何获得所需输出的任何想法

> C++中,可以使用Boost Rational类。但你需要给出分子和分母

为此,您需要找出输入字符串中小数点后的数字。您可以通过字符串操纵函数来实现这一点。逐个字符读取输入的字符,并在
后找不到任何字符

char inputstr[30]; 
int noint=0, nodec=0;
char intstr[30], dec[30];
int decimalfound = 0;
int denominator = 1;
int numerator;

scanf("%s",inputstr);

len = strlen(inputstr);

for (int i=0; i<len; i++)
{
    if (decimalfound ==0)
    {
        if (inputstr[i] == '.')
        {
            decimalfound = 1;
        }
        else
        {
            intstr[noint++] = inputstr[i];
        }
     }
     else
     {
        dec[nodec++] = inputstr[i];
        denominator *=10;
     }
}
dec[nodec] = '\0';
intstr[noint] = '\0';

numerator = atoi(dec) + (atoi(intstr) * 1000);

// You can now use the numerator and denominator as the fraction, 
// either in the Rational class or you can find gcd and divide by 
// gcd.
charinputstr[30];
int noint=0,nodec=0;
char intstr[30],dec[30];
整数分频=0;
int分母=1;
整数分子;
scanf(“%s”,inputstr);
len=strlen(inputstr);

对于(int i=0;i我希望我能原谅我发布了一个“只使用
C
语言”的答案。我知道你用
C++
标记了这个问题-但是我不能拒绝这个诱饵,对不起。这至少仍然是有效的
C++
(当然,它主要使用C字符串处理技术)

输出:

30047/2000
完整示例见

注意事项:

int rc = num_string_float_to_rat("0015.0235", &num, &den);
// Check return code -> should be 0!
printf("%ld/%ld\n", num, den);
  • strtok()
    用于将输入解析为令牌(无需在这方面重新发明轮子)。
    strtok()
    修改其输入-因此使用临时缓冲区以确保安全
  • 它检查无效字符-如果找到,将返回非零返回码
  • 使用了
    strtol()
    而不是
    atoi()
    ——因为它可以检测输入中的非数字字符
  • scanf()
    未被用于含糊输入-由于浮点数的舍入问题
  • strtol()
    的基数已明确设置为
    10
    ,以避免前导零出现问题(否则前导零将导致数字被解释为八进制)
  • 它使用一个
    num\u simple\u fraction()
    helper(未显示)——它反过来使用一个
    gcd()
    helper(也未显示)——将结果转换为一个简单的分数
  • 分子的log10()是通过计算小数点后标记的长度来确定的

    • 这个简单的代码怎么样:

      double n = 1.375;
      int num = 1, den = 1;
      double frac = (num * 1.f / den);
      double margin = 0.000001;
      while (abs(frac - n) > margin){
          if (frac > n){
              den++;
          }
          else{
              num++;
          }
          frac = (num * 1.f / den);
      }
      

      我没有做太多的测试,这只是一个想法。

      我会分三步来做

      1) 找到小数点,这样你就知道分母有多大了

      2) 得到分子。这只是删除小数点的原始文本

      3) 得到分母。如果没有小数点,分母是1。否则,分母为10^n,其中n是(现在已删除)小数点右侧的位数

      struct fraction {
          std::string num, den;
      };
      
      fraction parse(std::string input) {
          // 1:
          std::size_t dec_point = input.find('.');
      
          // 2:
          if (dec_point == std::string::npos)
              dec_point = 0;
          else {
              dec_point = input.length() - dec_point;
              input.erase(input.begin() + dec_point);
          }
      
          // 3:
          int denom = 1;
          for (int i = 1; i < dec_point; ++i)
              denom *= 10;
          string result = { input, std::to_string(denom) };
          return result;
      }
      
      结构分数{
      std::string num,den;
      };
      分数分析(标准::字符串输入){
      // 1:
      std::size\t dec\u point=input.find('.');
      // 2:
      if(dec_point==std::string::npos)
      dec_点=0;
      否则{
      dec_point=input.length()-dec_point;
      input.erase(input.begin()+dec_点);
      }
      // 3:
      int-denom=1;
      对于(int i=1;i
      您并没有真正指定是否需要转换浮点或字符串与比率,因此我将假设为前者

      您可以直接使用编码的属性,而不是尝试基于字符串或算术的方法

      浮点(标准称为
      binary32
      )在内存中编码如下:

       S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
       ^                                ^
      bit 31                           bit 0
      
      value = (-1)^S * significand * 2 ^ expoenent
      
      where:
          significand = 1.MMMMMMMMMMMMMMMMMMMMMMM (as binary)
          exponent = EEEEEEEE (as binary) - 127
      
      (-1)^S * significand * exponent = (-1)^s * (significand * 2^23) * 2 ^ (exponent - 23)
      
      float fv = 1.375f;
      Ratio rv = Ratio::fromFloat(fv);
      std::cout << "fv = " << fv << ", rv = " << rv << ", rv.toFloat() = " << rv.toFloat() << "\n";
      
      其中,
      S
      是符号位,
      E
      S是指数位(其中8位)
      M
      S是尾数位(23位)

      数字可以按如下方式解码:

       S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
       ^                                ^
      bit 31                           bit 0
      
      value = (-1)^S * significand * 2 ^ expoenent
      
      where:
          significand = 1.MMMMMMMMMMMMMMMMMMMMMMM (as binary)
          exponent = EEEEEEEE (as binary) - 127
      
      (-1)^S * significand * exponent = (-1)^s * (significand * 2^23) * 2 ^ (exponent - 23)
      
      float fv = 1.375f;
      Ratio rv = Ratio::fromFloat(fv);
      std::cout << "fv = " << fv << ", rv = " << rv << ", rv.toFloat() = " << rv.toFloat() << "\n";
      
      (注:这是所谓的“正常数”,也有零、次正常数、无穷和N-参见维基百科第一页链接)

      这里可以用这个。我们可以这样重写上面的等式:

       S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
       ^                                ^
      bit 31                           bit 0
      
      value = (-1)^S * significand * 2 ^ expoenent
      
      where:
          significand = 1.MMMMMMMMMMMMMMMMMMMMMMM (as binary)
          exponent = EEEEEEEE (as binary) - 127
      
      (-1)^S * significand * exponent = (-1)^s * (significand * 2^23) * 2 ^ (exponent - 23)
      
      float fv = 1.375f;
      Ratio rv = Ratio::fromFloat(fv);
      std::cout << "fv = " << fv << ", rv = " << rv << ", rv.toFloat() = " << rv.toFloat() << "\n";
      
      关键是
      有效位*2^23
      是一个整数(等于
      1.mmmmmmmmmmmmmmmm
      ,二进制-通过乘以2^23,我们将点向右移动了23位)。
      2^(指数-23)
      显然也是一个整数

      换句话说:我们可以将数字写为:

      (significand * 2^23) / 2^(-(exponent - 23))    (when exponent - 23 < 0)
      or
      [(significand * 2^23) * 2^(exponent - 23)] / 1 (when exponent - 23 >= 0)
      
      (有效位*2^23)/2^(-(指数-23))(当指数-23<0时)
      或
      [(有效位*2^23)*2^(指数-23)]/1(指数-23>=0时)
      
      所以我们有分子和分母-直接来自数字的二进制表示


      以上所有功能都可以在C++中实现:

      struct Ratio
      {
          int64_t numerator; // numerator includes sign
          uint64_t denominator;
      
          float toFloat() const
          {
              return static_cast<float>(numerator) / denominator;
          }
      
          static Ratio fromFloat(float v)
          {
              // First, obtain bitwise representation of the value
              const uint32_t bitwiseRepr = *reinterpret_cast<uint32_t*>(&v);
      
              // Extract sign, exponent and mantissa bits (as stored in memory) for convenience:
              const uint32_t signBit = bitwiseRepr >> 31u;
              const uint32_t expBits = (bitwiseRepr >> 23u) & 0xffu; // 8 bits set
              const uint32_t mntsBits = bitwiseRepr & 0x7fffffu; // 23 bits set
      
              // Handle some special cases:
              if(expBits == 0 && mntsBits == 0)
              {
                  // special case: +0 and -0
                  return {0, 1};
              }
              else if(expBits == 255u && mntsBits == 0)
              {
                  // special case: +inf, -inf
                  // Let's agree that infinity is always represented as 1/0 in Ratio 
                  return {signBit ? -1 : 1, 0};
              }
              else if(expBits == 255u)
              {
                  // special case: nan
                  // Let's agree, that if we get NaN, we returns max int64_t by 0
                  return {std::numeric_limits<int64_t>::max(), 0};
              }
      
              // mask lowest 23 bits (mantissa)
              uint32_t significand = (1u << 23u) | mntsBits;
      
              const int64_t signFactor = signBit ? -1 : 1;
      
              const int32_t exp = expBits - 127 - 23;
      
              if(exp < 0)
              {
                  return {signFactor * static_cast<int64_t>(significand), 1u << static_cast<uint32_t>(-exp)};
              }
              else
              {
                  return {signFactor * static_cast<int64_t>(significand * (1u << static_cast<uint32_t>(exp))), 1};
              }
          }
      };
      
      结构比率
      {
      int64\u t分子;//分子包含符号
      uint64_t分母;
      float toFloat()常量
      {
      返回静态类型(分子)/分母;
      }
      浮点数的静态比率(浮点数v)
      {
      //首先,获取值的按位表示
      const uint32_t bitwiseRepr=*重新解释类型(&v);
      //为方便起见,提取符号、指数和尾数位(存储在内存中):
      constuint32\u t signBit=bitwiseRepr>>31u;
      const uint32_t expBits=(bitwiseRepr>>23u)&0xffu;//设置8位
      const uint32\u t mntsBits=bitwiseRepr&0x7fffffu;//设置23位
      //处理一些特殊情况:
      if(expBits==0&&mntsBits==0)
      {
      //特殊情况:+0和-0
      返回{0,1};
      }
      else if(expBits==255u&&mntsBits==0)
      {
      //特殊情况:+inf,-inf
      //让我们同意无穷大总是以1/0的比例表示
      返回{signBit?-1:1,0};
      }
      else if(expBits==255u)
      {
      //特例:南
      //让我们同意,如果得到NaN,则返回max int64\u t乘以0
      返回{std::numeric_limits::max(),0};
      }