将浮点数转换为不同的基数

时间:2013-04-15 15:52:36

标签: c++ floating-point

我有一个自定义代码,用于将浮点数从基数10转换为另一个在标准输入上读入的基数。在浮点浮点之前转换为数字的另一个基数是通过将其除以基数并向后写入数字来实现的。浮点后的数字的转换是通过将它们乘以基数来实现的,并且在此临时结果中顺序写入浮点之前的数字。

问题在于我是一个事实的受害者,一些浮点数(如基数10中的0.8)在二进制中没有有限的表示(所以它们写成7.9999 ......)。因此,对于输入2.8,或任何大于2的输入,并以.8,(2.83.84.8)结束,即使我离开基地10,我得到输出:(2.79999 ...,3.79999 ......,4.79999 ......)。

问题是:如何解决这个问题,为什么我不能在0.8或1.8时遇到同样的错误?

以下是代码:

#include <iostream>

using namespace std;

void printInt(int *a,int k,int base)
{
    if (base<10){
        for (int i=k-1;i>=0;i--)
            cout << a[i];
    }else{
        for (int i=k-1;i>=0;i--)
        {
            if (a[i]<10)
                cout<<a[i];
            else if (a[i]==10)
                cout<<"A";
            else if (a[i]==11)
                cout<<"B";
            else if (a[i]==12)
                cout<<"C";
            else if (a[i]==13)
                cout<<"D";
            else if (a[i]==14)
                cout<<"E";
            else cout<<"F";

        }
    }
}

void printRem(int *a,int k,int base)
{
    if (base<10)
    {
        for(int i=0;i<k;i++){
            cout<<a[i];
        }
    }else{
        for(int i=0;i<k;i++)
        {
            if (a[i]<10)
                cout<<a[i];
            else if (a[i]==10)
                cout<<"A";
            else if (a[i]==11)
                cout<<"B";
            else if (a[i]==12)
                cout<<"C";
            else if (a[i]==13)
                cout<<"D";
            else if (a[i]==14)
                cout<<"E";
            else cout<<"F";

        }
    }
}

int main ()
{
    double n;
    int base;

    cin>>n;
    cin>>base;

    int *whole,*rem,numWhole,numRem;

    whole=NULL;
    numWhole=0;
    rem=NULL;
    numRem=0;

    double floatPart= n - (int)n;
    int intPart=(int)n;

    while (intPart!=0)
    {
        int *temp=new int[numWhole+1];

        int remainder;

        remainder=intPart%base;

        intPart=intPart/base;

        if (whole!=NULL)
            for (int i=0;i<numWhole;i++)
                temp[i]=whole[i];

        delete [] whole;
        temp[numWhole] = remainder;

        whole=temp;
        numWhole++;
    }

    while (floatPart!=0)
    {
        int *temp=new int[numRem+1];

        double nov;
        nov=floatPart*base;

        if (rem!=NULL)
            for (int i=0;i<numRem;i++)
                temp[i]=rem[i];

        temp[numRem]=(int)nov;

        numRem+=1;
        delete [] rem;
        rem=temp;

        floatPart=nov-int(nov);

        if (numRem==10)
            break;
    }

    printInt(whole,numWhole,base);
    if (rem!=NULL) cout<<".";
    printRem(rem,numRem,base);
    cout<<endl;

    cin >> n;

    return 0;
}

2 个答案:

答案 0 :(得分:2)

  

为什么我在0.8或1.8时没有得到同样的错误?

在这些情况下,当您存储到double时,您仍然舍入结果。所有你观察到的是,舍入有时会给你你想要的答案。

  

我该如何解决这个问题?

doubleIEEE-754的(强)可能性中,它具有大约16位的准确度。

如果您对准确度较低的数字感到满意,可以对基数为10的结果进行舍入。

当您获得任何结果时,例如2.7999999,将其四舍五入为数字。

答案 1 :(得分:1)

只要将值存储在浮点类型中,就会丢失原始值。在这种情况下,某些数字(如0.8会因略微变大而失去原始值,而2.8等其他数字会因原始值变小而失去原始值。

在任何情况下,正常的解决方案是不使用浮点数(使用固定点或字符串表示),或者在显示期间舍入到小数点后的位数。