浮動小数点数を基数 10 から標準入力で読み込まれる別の基数に変換するためのカスタム コードがあります。float の浮動小数点の前の数字の別の基数への変換は、浮動小数点数を基数で割り、数値を逆に書き込むことによって実装されます。浮動小数点に続く桁の変換は、それらに基数を乗算し、浮動小数点の前の桁をこの一時的な結果に順番に書き込むことによって実装されます。
問題は、基数 10 の 0.8 などの一部の浮動小数点数がバイナリで有限表現を持たないという事実の犠牲者であることです (したがって、7.9999 と書かれています...)。したがって、 input 2.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;
}