例24 數制轉換
題目描述
請你編一程式實作兩種不同進制之間的資料轉換,
輸入格式
共三行,第一行是一個正整數,表示需要轉換的數的進制n(2≤n≤16),第二行是一個n進制數,若n>10則用大寫字母A-F表示數碼10-15,并且該n進制數對應的十進制的值不超過1000000000,第三行也是一個正整數,表示轉換之后的數的進制m(2≤m≤16),
輸出格式
一個正整數,表示轉換之后的m進制數,
輸入樣例
16
FF
2
輸出樣例
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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/207638.html
標籤:C
上一篇:C語言筆記 04_運算子
