【问题标题】:c++ Converting octal fraction to decimal fraction?c ++将八进制分数转换为十进制分数?
【发布时间】:2017-02-19 00:00:43
【问题描述】:

我目前正在开发一个程序,该程序旨在将八进制分数作为输入并将其转换为十进制分数。到目前为止,我有部分代码可以将小数点前的部分转换为小数点,而不是小数点后的浮点数。我试图使用模数,但由于我的变量是浮点数而没有成功。

有没有办法将小数点后的剩余数字从八进制转换为十进制?我在下面发布了我的代码。任何帮助表示赞赏。谢谢!

int main()
{
    float num;
    int rem = 0;;
    int dec = 0;
    int i = 0;

    cout << "Please enter a number with a decimal point: ";
    cin >> num;

    double ohalf = num - (int)num;
    int half = num;

    while (half != 0)
    {
        rem = half % 10;
        half /= 10; //Converts first have to decimal
        dec += rem *= pow(8, i);
        i++;
    }
    cout << dec;

    i = -1;
    while (ohalf != 0)
    {
        rem = ohalf *pow(8, i); //Converts second half to decimal. *This is where I am stuck*
        i--;
    }
    cout << rem;

    _getch();
    return 0;
}

【问题讨论】:

  • 我认为将输入处理为stringsplit it at the '.' char 会容易得多,在拆分字符串上使用strtol,适当缩放小数部分,然后添加他们变成double

标签: c++ decimal octal


【解决方案1】:

我们的想法是,只要经常乘以底数就可以去掉小数点:

"123.456" in base 16 
=> BASE16("1234.56")/16 
=> BASE16("12345.6")/(16*16)
=> BASE16("123456")/(16*16*16)

or 

"123.456" in base 8
=> BASE8("1234.56")/8 
=> BASE8("12345.6")/(8*8)
=> BASE8("123456")/(8*8*8)

所以我们只需要知道小数点后的位数。 然后我们可以删除它并使用std::stoi 来转换所需基址中的剩余字符串。 作为最后一步,我们需要再次划分base^number_of_places_after_decimal

把所有东西放在一起,你会得到这样的东西:

#include <iostream>
#include <string>
#include <cmath>

using std::cout;
using std::cin;
using std::string;

int main()
{
    int base = 8;
    string value;

    cout << "Please enter a number with a decimal point: ";
    cin >> value;

    size_t ppos = value.find('.');
    if (ppos != string::npos) {
        value.replace(ppos,1,"");
    } else {
        ppos = value.size();
    }

    size_t mpos = 0;
    double dValue = (double)std::stoi(value, &mpos, base);
    if (mpos >= ppos)
    {
        dValue /= std::pow(base, (mpos - ppos));
    }

    std::cout << dValue << '\n';

    return 0;
}

【讨论】:

  • 我认为您最好将&amp;maxp 作为第二个参数传递给std::stoi,这样字符串中的任何尾随字符都不会被计算在内。
  • P.S.那不是“八进制点”而不是“小数点”吗? :-p
  • @TobySpeight 相应地调整了我的答案,感谢您指出这一点。我在文本中留下了decimal point 以与问题保持一致:-P
【解决方案2】:

如果您确信浮点值的整数和小数部分都不会超出long long int 的范围,您可以使用std::stoll() 分别解析这两个部分,然后将小数部分除以8 的适当幂:

#include <cmath>
#include <stdexcept>
#include <string>

double parse_octal_fraction(const std::string s)
{
    std::size_t dotpos;
    auto whole = std::stoll(s, &dotpos, 8);
    if (dotpos+1 >= s.length())
        // no fractional part
        return whole;

    std::size_t fract_digits;
    auto frac = std::stoll(s.substr(dotpos+1), &fract_digits, 8);

    if (s.find_first_not_of("01234567", dotpos+1) != std::string::npos)
        throw std::invalid_argument("parse_octal_fraction");

    return whole + frac / std::pow(8, fract_digits);
}

#include <iostream>
int main()
{
    for (auto input: { "10", "0", "1.", "0.4", "0.04", "1.04", "1.04 ", "1. 04"})
        try {
            std::cout << input << " (octal) == " << parse_octal_fraction(input) << " (decimal)" << std::endl;
        } catch (const std::invalid_argument e) {
            std::cerr << "invalid input: " << e.what() << " " << input << std::endl;
        }
}

显示的测试输入给出以下输出:

10(八进制)== 8(十进制)
0(八进制)== 0(十进制)
1.(八进制)== 1(十进制)
0.4(八进制)== 0.5(十进制)
0.04(八进制)== 0.0625(十进制)
1.04(八进制)== 1.0625(十进制)
无效输入:parse_octal_fraction 1.04
无效输入:parse_octal_fraction 1. 04

【讨论】:

    【解决方案3】:

    在你的代码中

     while (ohalf != 0)
    {
        rem = ohalf *pow(8, i); //Converts second half to decimal. *This is where I am stuck*
        i--;
    }
    

    ohalf 永远不会等于零,所以它可能导致无限循环

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-06
      • 2011-08-21
      • 1970-01-01
      • 2017-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多