Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting float to different base

I have a custom code for converting a floating-point number from base 10, to another base which is read in on the standard input. Conversion to another base of the digits before the floating point of the float is implemented by dividing it with the base, and writing the numbers backwards. Conversion of the digits following the floating point is implemented by multiplying them by the base, and writing the digits before the floating point in this temporary result sequentially.

The problem is that I am a victim of the fact that some floating point numbers such as 0.8 in base 10 do not have a finite representation in binary (so they're written as 7.9999...). Hence, for input 2.8, or any input that is larger than 2, and ends in .8, (2.8, 3.8, 4.8) even when I leave the base 10, I get outputs: (2.79999..., 3.79999..., 4.79999...).

The question is: how do I fix this and why don't I get the same mistake for 0.8 or 1.8?

Here is the code:

#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;
}
like image 826
repmaj Avatar asked Dec 06 '25 00:12

repmaj


2 Answers

why don't I get the same mistake for 0.8 or 1.8?

In those cases, you are still rounding the result when you store to double. All you are observing is that the rounding sometimes gives you the answer you want.

how do I fix this?

In the (strong) likelihood that your double is IEEE-754, it has about 16 digits of accuracy.

If you are content with fewer digits of accuracy, you can round your base 10 result.

When you get any result, such as 2.7999999, round it to fewer digits.

like image 192
Drew Dormann Avatar answered Dec 08 '25 15:12

Drew Dormann


As soon as you store the value in a floating point type, you lose the original value. In this case some number (like 0.8 lose the original value by becoming slightly larger while other numbers such as 2.8 lose the original value by becoming smaller.

In any case the normal solution is to either not use floating point numbers (using either fixed point or string representation), or during display to round to a number of digits after the decimal point.

like image 24
Mark B Avatar answered Dec 08 '25 15:12

Mark B



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!