C-注:進数システムとの間の変換の問題(数システム)

オリジナルリンク: http://c.biancheng.net/view/1725.html

簡単な紹介

現在のコンピュータの動作が、すぐに、それは内部的に使用するデータは、ヒト進数についての慣れていないですが、唯一のバイナリ1と0を含みます。我々は固定と番号システム、2進数に変換して計算するコンピュータへの入力をDECIMAL、そして私たちが必要とする十進数に変換し、バイナリで計算結果が、これらは、オペレーティングシステムによって自動的に行われます均一なルールと数値的方法を表す記号は、人々は通常数システム進、2進、8進および16進数を有しています。

バンドの基本的な考え方

2進、8進、10進、それまでの16進の違い:

  • デジタルデジタル進数0〜9、A〜Fのバイナリデジタル0と1で表される異なる範囲(個々のビットの数字)
  • 塩基は、(として使用することができるデジタル数)バイナリベース2、ベース16進数は異なります
  • 右ビット(のIビットのビット重み塩基例えば右として、左から右へ乗(I-1)は、1番、2番...されている)、1ビットの小数ビット位置123が10であります2,2- ^ビット-1,3- ^ 10 ^ 0重量右10ビットのビット位置である。進数1101 ^ 3左端2の右

2進、8進数、16進数加算と減算との間の差

バイナリ

バイナリと小数減算加算と減算を考え類似している:バイナリの場合、2進加算器によって実行される二時には、一つだけ減算来ます。

  • 2進加算:1 + 0 = 1 = 10 + 1、11 + 10 = 101、111 + 111 = 1110
    ここに画像を挿入説明
  • バイナリ減算:1-0 = 1,10-1 = 1,101-11 = 101 = 10,1100-111
    ここに画像を挿入説明

オクタル

0〜7の8進数8、加算演算にベース8は、わずか8、来るとき減算によって八時。例えば、デジタル0,1,5,7,14,733,67001,25430は有効進です。

  • オクタル添加:3 + 4 = 7、5 + 6 = 42 + 13.75 = 567 = 3216 + 137,2427

ここに画像を挿入説明

  • オクタル・減算:6-4 = 2,52-27 = 23,307-141 = 5757 = 146,7430-1451
    ここに画像を挿入説明

六角

進数は、10で表される、Bは11を表し、Cは12を表し、Dは13を表し、Eは14を表し、Fは15を表し、0〜F 16桁、ベース16を有しているため、加算器だけ付属します16に1,1場合16による減算。例えば、0,1,6,9は、A、D、F、419、EA32,80A3、BC00が有効な16進数字です。

  • 六角添加:6 + 7 = D 18 + BA = D2,595 + 792 = D27,2F87 + F8A = 3F11

ここに画像を挿入説明

  • 減算ヘキサン:D-3 = A、52-2F = 23、E07-141 = CC6,7CA0-1CB1 = 5FEF

ここに画像を挿入説明

数のシステム間の変換

シナリオ1、2進数、8進数、(概要:右を追加することによって)10進数に進

2進、8進変換を10進数に進数は、非常に簡単である「追加される右(右の位置)で」学生は、適切な場所を調べることができますかわかりません。
次に、現在の数はN進であると仮定する。

  • 对于整数部分,从右往左看,第 i 位的位权等于Ni-1
  • 对于小数部分,恰好相反,要从左往右看,第 j 位的位权为N-j

整数部分(不带小数)

将二进制数字11010转换成十进制:

11010 = 1×2^4 + 1×2^3 + 0×2^2 + 1×2^1 + 0×2^0 = 26(十进制)

八进制数字 53627 转换成十进制:

53627 = 5×8^4 + 3×8^3 + 6×8^2 + 2×8^1 + 7×8^0 = 22423(十进制)

十六进制数字 9FA8C 转换成十进制(将A~F对应的具体的数字计算):

9FA8C = 9×16^4 + 15×16^3 + 10×16^2 + 8×16^1 + 12×16^0 = 653964(十进制)

整数部分+小数部分

二进制数字1010.1101 转换成十进制:

1010.1101 = 1×2^3 + 0×2^2 + 1×2^1 + 0×2^0 + 1×2^-1 + 1×2^-2 + 0×2^-3 + 1×2^-4 = 10.8125(十进制)

八进制数字 423.5176 转换成十进制:

423.5176 = 4×82 + 2×81 + 3×80 + 5×8-1 + 1×8-2 + 7×8-3 + 6×8-4 = 275.65576171875(十进制)

小数部分和整数部分相反,要从左往右看,第1位的位权为 8-1=1/8,第2位的位权为 8-2=1/64,第3位的位权为 8-3=1/512,第4位的位权为 8-4=1/4096 …… 第m位的位权就为 8-m。

C语言实现代码(仅讨论整数):

/*
将一个2,8进制转换为十进制 (算法思维从高位到低位运算,暂时没考虑16进制) 
*/
#include <stdio.h>
#include <string.h>//strlen()
int OcToDec(char *a,int base);//将2,8进制数a转换为十进制数 
int main(void)
{
 char a[20];//a存放八进制整数
 int tennum;//存放a对应的十进制整数
 printf("请输入一个数:") ;
 scanf("%s",a);//输入的时候,a[20]={1,0,1}  
 int n;
 printf("请输入该数的基数(输入的是几进制基数就是几):");
 scanf("%d",&n);
 tennum=OcToDec(a,n);
 printf("%d进制数%s转换为十进制为:%d\n",n,a,tennum);
 return 0;
}
int OcToDec(char *a,int base)
{
 int sum=0;//变量sum存放a对应的十进制数 
 int len=strlen(a);//位数 
 int weight=1;//位权值
 for(int i=len-1;i>=0;i--)//将八进制从低位向高位输出, 即数组a下标最大的元素为八进制的最低位 
 {
  sum+=(a[i]-'0')*weight;//数组下标i越小,即八进制位数越高,位权weight越重 ,a[i]-'0'转化为Ascii码运算到到一个字符数字对应的整型数字 
  weight*=base; 
 } 
 return sum;
}

测试输出:
ここに画像を挿入説明
ここに画像を挿入説明
扩展:以下代码块将int OcToDec(char *a,int base)函数体修改一下,让其从二进制或八进制高位向低位扫描各位上的数,按权相加求和。其中base为基数2或8

int OcToDec(char *a, int base)   //将base(8)进制数a转换成十进制数 
{
 int sum = 0;              
    int len = strlen(a);    
            
 for(int i = 0;i < len;i++)
 {  
     sum = sum * base + a[i] - '0';      
 }
 return sum;
}

情景二、将十进制转换为二进制、八进制、十六进制(总结:整数部分为除 N 取余,逆序排列,小数部分为乘 N 取整,顺序排列N为要转换对应进制的基数

将十进制转换为其它进制时比较复杂,整数部分和小数部分的算法不一样。如果一个数字既包含了整数部分又包含了小数部分,那么将整数部分和小数部分开,分别按照上面的方法完成转换,然后再合并在一起即可。

整数部分(不带小数)

具体做法:

  • 将 N (要转化的目标进制的基数) 作为除数,用十进制整数除以 N,可以得到一个商和余数;
  • 保留余数,用商继续除以 N,又得到一个新的商和余数;
  • 仍然保留余数,用商继续除以 N,还会得到一个新的商和余数;
  • 如此反复进行,每次都保留余数,用商接着除以 N,直到商为 0 时为止。

将十进制数字 36926 转换成八进制:
ここに画像を挿入説明
结果为110076(八进制)。

将十进制数字 42 转换成二进制的过程:
ここに画像を挿入説明

结果为101010(二进制)

整数部分+小数部分

具体做法:

  • 用 N(要转化的目标进制的基数) 乘以十进制小数,可以得到一个积,这个积包含了整数部分和小数部分;
  • 将积的整数部分取出,再用 N 乘以余下的小数部分,又得到一个新的积;
  • 再将积的整数部分取出,继续用 N 乘以余下的小数部分;
  • 如此反复进行,每次都取出整数部分,用 N 接着乘以小数部分,直到积中的小数部分为 0,或者达到所要求的精度为止。

十进制小数 0.930908203125 转换成八进制小数的过程:
ここに画像を挿入説明
十进制小数 0.930908203125 转换成八进制小数的结果为 0.7345。

十进制小数 0.6875 转换成二进制小数的过程:
ここに画像を挿入説明
十进制小数 0.6875 转换成二进制小数的结果为 0.1011。

C语言实现代码(仅讨论整数):

/*
将十进制转换为2,8,16进制 
*/
#include <stdio.h>
#include <string.h>
void DToM(int d,int m,char *mnum);//D->decimalism 
int main(void)
{
 int d;//存放输入的十进制数
 printf("请输入一个待转换的十进制数:"); 
 scanf("%d",&d);
 int M;
 printf("请输入要转换的进制(2,8,16):");
 scanf("%d",&M);
 char Mnum[100];//存放十进制数d对应的M进制数
 DToM(d,M,Mnum);
 printf("该十进制数对应的%d进制数为:%s\n",M,Mnum); 
 return 0;
}
void DToM(int d,int m,char *mnum)//d为十进制数,m为要转换的目标进制数,mnum指向的数组存放转换结果 
{
 int len=0,r=0;//存放mnum指向数组的下标以及余数 
 do
 {//除M取余 
  r=d%m;
  if(r >= 10) //针对要转换为16进制的情况 
         mnum[len++] = r - 10 + 'A';   //将对应的整数转换成字母字符
     else      
         mnum[len++] = r + '0';     //将对应的整数转换成数字字符
  d/=m;
 }while(d!=0);
 mnum[len]='\0';
 char t;
 for(int i=0,j=len-1;i<j;i++,j--)//逆置输出 
 {
  t=mnum[i];
  mnum[i]=mnum[j];
  mnum[j]=t;
 }
}

测试输出:
ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明

情景三、二进制和八进制、十六进制的转换(总结:通常二进制的3位分别用八进制的3位和十六进制的4位来表示)

首先可以使用上面的方法

  • 将二进制转换为十进制(对应上文讲到的情景一),然后十进制转换为对应的的八进制和十六进制(对应上文讲到的情景二)
  • 亦或者将八进制和十六进制转换为十进制(情景一),然后十进制转化为二进制(情景二)

C语言实现代码(将情景一和情景二的代码整合一下,即借助十进制数作为中介):

/*
N进制到M进制 
*/ 
#include <stdio.h>
#include <string.h>
int NToD(char *a,int base);//将N进制数a转换为十进制数 (N可以考虑二、八、十六进制)
void DToM(int d,int m,char *mnum);//再将十进制转换成M进制(M可以考虑二,八,十六进制)
int getIndexOfSigns(char *ch);//NtoD函数内调用
int main(void)
{
 int N,M;//要将N进制数转换成M进制数 
 char Nnum[20],Mnum[20];//存放N进制数以及转换后的M进制数
 printf("要将N进制数Nnum转换成M进制数请输入以下格式\nN Nnum M:"); 
 scanf("%d %s %d",&N,Nnum,&M);
 int d=NToD(Nnum,N);//将N进制数Nnum转换成十进制数d
 DToM(d,M,Mnum);//将十进制数d转换成M进制数Mnum
 printf("%d进制数%s转换成%d进制数为:%s\n",N,Nnum,M,Mnum); 
 return 0; 
}
int NToD(char *a,int base)
{
 int sum=0;//变量sum存放a对应的十进制数 
 int len=strlen(a);//位数 
 int weight=1;//位权值
 for(int i=len-1;i>=0;i--)//将N进制从低位向高位输出, 即数组a下标最大的元素为八进制的最低位 
 {
  sum+=(getIndexOfSigns(a[i]))*weight;//数组下标i越小,即八进制位数越高,位权weight越重 ,a[i]-'0'将字母映射为十进制数 
  weight*=base; 
 } 
 return sum;
}
void DToM(int d,int m,char *mnum)
{
 int len=0,r=0;//存放mnum指向数组的下标以及余数 
 do
 {//除M取余 
  r=d%m;
  if(r >= 10) //针对要转换为16进制的情况 
         mnum[len++] = r - 10 + 'A';   //将对应的整数转换成字母字符
     else      
         mnum[len++] = r + '0';     //将对应的整数转换成数字字符
  d/=m;
 }while(d!=0);
 mnum[len]='\0';
 char t;
 for(int i=0,j=len-1;i<j;i++,j--)//逆置输出 
 {
  t=mnum[i];
  mnum[i]=mnum[j];
  mnum[j]=t;
 }
}
int getIndexOfSigns(char *ch)
{
    if(ch >= '0' && ch <= '9')
    {
        return ch - '0';
    }
    if(ch >= 'A' && ch <='F') 
    {
        return ch - 'A' + 10;
    }
    if(ch >= 'a' && ch <= 'f')
    {
        return ch - 'a' + 10;
    }
    return -1;
}

情况三代码是对情况一和情况二的综合,将情况一的int OcToDec()改了一下见名知意的名字int NToD(),内部代码块没改,然后直接使用情况二的void DToM(),然后多加了一个int getIndexOfSigns(char *ch)增加了情况一对16进制的支持。

(機能が改善された場合には、小数点への変換進数をサポートする)テスト出力:
ここに画像を挿入説明
ここに画像を挿入説明

ここでは単純なアプローチを使用しています。

バイナリと進整数の整数変換

進整数の8進整数、それぞれ3桁の2進数だけ正確に0 7,3ビットのバイナリビット3〜7の最大値、及び進デジタルすることができる起因進数に(8進数に変換すると、右により追加されます)進数を得るために、動作の順序を順次下位ビットから行われる三ゼロパディング不十分高い、最終的には一緒にスプライス。

1674年のオクタル結果にバイナリ整数1110111100:

ここに画像を挿入説明
結果は、1674(8進数)であります

進整数に場合進整数毎、3進数をバイナリデジットに変換されるという考え方とは反対であり、動作の順序は、ローからハイへの順で行われます。次の図は、2743進進整数を変換する方法を示しています
ここに画像を挿入説明
(バイナリ)010 111 100 011結果

二進と16進整数の整数変換

進整数のバイナリ整数は、各4進数は16進数に変換すると、動作の順序はゼロ未満4つの高パッド入り、ローからハイに順次行われます。次の図は、バイナリ整数10,110,101,011,100変換ヘクスする方法を示しています。
ここに画像を挿入説明
進結果2D5Cに変換バイナリ整数10,110,101,011,100は(注:小数Yaoanは16進数表現に対応します表記)。

進整数に進整数は、すべての4桁の16進数がバイナリデジットに変換されるアイデアの反対である場合、動作の順序は、ローからハイに順に行われます。次の図は、バイナリに進整数A5D6を変換する方法を示しています。

ここに画像を挿入説明
図から分かるように、結果は、A5D6は1,010,010,111,010,110バイナリ進整数に変換されます。

おすすめ

転載: blog.csdn.net/weixin_42124234/article/details/101616137