C語言程序設計100例之(24):數制轉換

例24   數制轉換

題目描述git

請你編一程序實現兩種不一樣進制之間的數據轉換。編程

輸入格式測試

共三行,第一行是一個正整數,表示須要轉換的數的進制n(2≤n≤16),第二行是一個n進制數,若n>10則用大寫字母A-F表示數碼10-15,而且該n進制數對應的十進制的值不超過1000000000,第三行也是一個正整數,表示轉換以後的數的進制m(2≤m≤16)。spa

輸出格式設計

一個正整數,表示轉換以後的m進制數。ci

輸入樣例string

16it

FFio

2table

輸出樣例

11111111

        (1)編程思路。

        十進制整數轉換爲R進制整數的基本方法是:「除R取餘」。具體作法爲:對於十進制數整數,用R連續除要轉換的十進制整數及各次所得之商,直除到商等於0時爲止,則各次所得之餘數即爲所求R進制整數由低位到高位的值。這個過程能夠寫成一個簡單的循環。

        通常而言,對於任意的R進制數 An-1An-2…A1A0能夠表示爲如下和式:

         An-1×Rn-1 +…+A1×R1+A0×R0 (其中R爲基數)

        這個和式也稱爲「按權展開式」。

        R進制數轉換爲十進制數的基本方法是將R進制數的各位按權展開相加便可。

        本例的思路是:將輸入的n進制整數按權值展開後轉換爲十進制整數,再將所得的十進制整數採用「除m取餘」轉換爲m進制整數便可。

        (2)源程序。

#include <stdio.h>

int main()

{

    char table[17]="0123456789ABCDEF";

    int n,m;

    char s[33];

    scanf("%d",&n);

    scanf("%s",s);

    scanf("%d",&m);

    int num=0;

    for (int i=0;s[i]!='\0';i++)     // n進制整數按權值展開後轉換爲十進制整數num

    {

        if (s[i]>='0' && s[i]<='9')

            num=num*n+s[i]-'0';

        else

            num=num*n+s[i]-'A'+10;

    }

    int digit[32],cnt=0;

    do {                   // 十進制整數採用「除m取餘」轉換爲m進制整數

        digit[cnt++]=num%m;

        num=num/m;

    } while (num!=0);

    for (int i=cnt-1;i>=0;i--)

        printf("%c",table[digit[i]]);

    printf("\n");

    return 0;

}

習題24

24-1  高低位交換

        本題選自洛谷題庫 (https://www.luogu.org/problem/P1100)。

題目描述

給出一個小於232的正整數。這個數能夠用一個32位的二進制數表示(不足32位用0補足)。咱們稱這個二進制數的前16位爲「高位」,後16位爲「低位」。將它的高低位交換,咱們能夠獲得一個新的數。試問這個新的數是多少(用十進制表示)。

例如,數1314520用二進制表示爲00000000000101000000111011011000(添加了11個前導0補足爲32位),其中前16位爲高位,即0000000000010100;後16位爲低位,即0000111011011000。將它的高低位進行交換,咱們獲得了一個新的二進制數00001110110110000000000000010100。它便是十進制的249036820。

輸入格式

一個小於232的正整數。

輸出格式

將新的數輸出

輸入樣例

1314520

輸出樣例

249036820

        (1)編程思路。

        將輸入的十進制整數採用「除2取餘」轉換爲二進制整數,再將所得的二進制整數依照低16位在前高16位在後的方式按權值展開後轉換爲十進制整數便可。

        (2)源程序。

#include <stdio.h>

int main()

{

    unsigned int num;

    scanf("%d",&num);

    int digit[32]={0},cnt=0;

    do {                   // 十進制整數採用「除2取餘」轉換爲二進制整數

        digit[cnt++]=num%2;

        num=num/2;

    } while (num!=0);

    int i;

    for (i=15;i>=0;i--)            // 先將低16位按權值展開

        num=num*2+digit[i];

    for (i=31;i>=16;i--)           // 再將高16位按權值展開

        num=num*2+digit[i];

    printf("%u\n",num);

    return 0;

}

24-2  進制轉換

        本題選自洛谷題庫 (https://www.luogu.org/problem/P1017)。

題目描述

通常說來,任何一個正整數R或一個負整數-R均可以被選來做爲一個數制系統的基數。若是是以R或-R爲基數,則須要用到的數碼爲 0,1,....R-1。例如,當R=7時,所需用到的數碼是0,1,2,3,4,5和6,這與其是R或-R無關。若是做爲基數的數絕對值超過10,則爲了表示這些數碼,一般使用英文字母來表示那些大於9的數碼。例如對16進制數來講,用A表示10,用B表示11,用C表示12,用D表示13,用E表示14,用F表示15。

在負進制數中是用-R做爲基數,例如-15 (十進制)至關於110001 (-2進制),而且它能夠被表示爲2的冪級數的和數:

110001=1×(−2)5 +1×(−2)4 +0×(−2)3 +0×(−2)2 +0×(−2)1 +1×(−2)0

設計一個程序,讀入一個十進制數和一個負進制數的基數,並將此十進制數轉換爲此負進制下的數:-R∈{-2,-3,-4,...,-20}

輸入格式

輸入包括多組測試數據。

每組測試數據佔一行,每行有兩個輸入數據。

第一個是十進制數N (−32768≤N≤32767)

第二個是負進制數的基數-R。

輸出格式

結果顯示在屏幕上,相對於輸入,應輸出此負進制數及其基數,若此基數超過10,則參照16進制的方式處理。

輸入樣例

30000 -2

-20000 -2

28800 -16

-25000 -16

輸出樣例

30000=11011010101110000(base-2)

-20000=1111011000100000(base-2)

28800=19180(base-16)

-25000=7FB8(base-16)

        (1)編程思路。

        咱們知道十進制整數是採用「除R取餘」轉換爲R進制整數的,對於負基數(-R)一樣如此。

        先看問題描述中的例子-15轉換爲-2進制數。在C語言中「除R取餘」運算過程爲:

被除數

除數

餘數

-15

-2

7

-1

7

-2

-3

1

-3

-2

1

-1

1

-2

0

1

        這裏餘數出現了負數,須要將餘數轉換成正數,怎麼處理呢?

        由於, 被除數=商*除數+餘數=商*除數+除數+餘數-除數=(商+1)*除數+(餘數-除數)。所以,若餘數爲負時,只須要將商+1,餘數-除數,就能夠將餘數轉換爲正數。

被除數

除數

餘數

校訂的商

校訂餘數

-15

-2

7

-1

8

1

8

-2

-4

0

 

 

-4

-2

2

0

 

 

2

-2

-1

0

 

 

-1

-2

0

-1

1

1

1

-2

0

1

 

 

         所以,-15轉換爲-2進制數爲110001。

         (2)源程序。

#include <stdio.h>

int main()

{

    char table[21]="0123456789ABCDEFGHIJ";

    int num,r;

    while (scanf("%d%d",&num,&r)!=EOF)

    {

        printf("%d=",num);

        int digit[32]={0},cnt=0;

        do {

           int t=num%r;

           num=num/r;

           if (t<0) {t=t-r; num++; }

           digit[cnt++]=t;

        } while (num!=0);

        int i;

        for (i=cnt-1;i>=0;i--)

          printf("%c",table[digit[i]]);

        printf("(base%d)\n",r);

    }

    return 0;

}

24-3  彩燈和按鈕

問題描述

有一個機器,它有 m(2≤m≤30) 個彩燈和一個按鈕。每按下按鈕時,最右邊的彩燈會發生一次變換。變換爲:①若是當前狀態爲紅色,它將變成綠色;②若是當前狀態爲綠色,它將變成藍色;③若是當前狀態爲藍色,它將變成紅色,而且它左邊的彩燈(若是存在)也會發生一次變換。初始狀態下全部的彩燈都是紅色的。

輸入格式

輸入包括多組測試,第1行給出正整數T(1≤T≤15),表示測試數據的組數。

每組測試數據包括兩個整數m(2≤m≤30) 和 n(1≤n<263),分別表示彩燈的個數和按鈕被按下的次數。

輸出格式

對每組測試數據,按從左到右的順序輸出各彩燈的顏色狀態,R 表示紅色,G表示綠色,B 表示藍色。

輸入樣例

2

3 1

2 3

輸出樣例

RRG

GR

        (1)編程思路。

        每按一次按鈕都是從最右邊的彩燈開始變換,將m個彩燈能夠當作一個m位數,最右邊的彩燈爲其個位數,每按一次按鈕能夠當作個位數加1。每按三次後從右數第二個彩燈纔會變一下,每按9次從右邊數第三個彩燈會變換一次,……。

        顯然,m個彩燈表示的m位數能夠當作是一個三進制數,紅燈表示0,綠燈表示1,藍燈表示2,將輸入的n轉換爲3進制數便可。

        (2)源程序。

#include <stdio.h>

#include <string.h>

int main()

{

    char table[4]="RGB";

    int t, m, len;

    long long n;

    int color[30];

    scanf("%d", &t);

    while(t--)

    {

        memset(color, 0, sizeof(color));

        scanf("%d%lld", &m, &n);

        len = m;

        while (n > 0 && m > 0)

        {

            color[--m] = n % 3;

            n /= 3;

        }

        for (int i=0; i<len; i++)

            putchar(table[color[i]]);

        putchar('\n');

    }

   return 0;

}

相關文章
相關標籤/搜索