3

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

问题是我是这样一个事实的受害者,例如以 10 为底的 0.8 之类的浮点数在二进制中没有有限表示(因此它们被写为 7.9999 ...)。因此,对于 input2.8或任何大于 2 且以 .8 结尾的输入,( 2.8, 3.8, 4.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;
}
4

2 回答 2

2

为什么0.8或1.8不会出现同样的错误?

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

我该如何解决?

您很可能doubleIEEE-754,它的准确度约为 16 位数。

如果您满足于较少的精度位数,您可以将您的以 10 为底的结果四舍五入。

当您得到任何结果时,例如2.7999999,将其四舍五入到更少的数字。

于 2013-04-15T16:03:58.113 回答
1

一旦将值存储为浮点类型,就会丢失原始值。在这种情况下,某些数字(例如0.8通过变大而失去原始值,而其他数字(例如2.8通过变小而失去原始值)。

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

于 2013-04-15T16:01:12.693 回答