■新しいC23仕様のC言語では2進数が使える
#include <stdio.h>
int main(void){
//2進定数を2進数のprintf書式で表示する
printf("%b\n",0b11110000);
}
●gcc version 12.2.0の実行結果
注意:
2024年9月現在C23に対応しているコンパイラは少ないので
読者の環境下ではうまく動かないかもしれません。
■以下に示す自作10進/2進変換の課題はもうすぐ時代遅れになります。
■10進数値を2進文字列変換
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
// 16進⇒二進変換表
static char *cnv16to2[] = {
[0] ="0000",[1] ="0001",[2] ="0010",[3] ="0011",
[4] ="0100",[5] ="0101",[6] ="0110",[7] ="0111",
[8] ="1000",[9] ="1001",[0xa]="1010",[0xb]="1011",
[0xc]="1100",[0xd]="1101",[0xe]="1110",[0xf]="1111",
};
// 十進数値⇒二進文字列変換
char *dec2bin(unsigned int x) {
static char output[256];
sprintf(output,
"%s%s%s%s%s%s%s%s",
cnv16to2[(x & 0xF0000000) >> 28],
cnv16to2[(x & 0x0F000000) >> 24],
cnv16to2[(x & 0x00F00000) >> 20],
cnv16to2[(x & 0x000F0000) >> 16],
cnv16to2[(x & 0x0000F000) >> 12],
cnv16to2[(x & 0x00000F00) >> 8],
cnv16to2[(x & 0x000000F0) >> 4],
cnv16to2[(x & 0x0000000F) ]
);
return output ;
}
intは32bitを前提としています。
■2進数文字列を10進数値に変換
// 二進文字列⇒十進数値変換
// 1111 = 2^3+2^2+2^1+2^0
// = 1<<3+1<<2+1<<1+1<<0;
// 1010
// = 1<<3+0<<2+1<<1+0<<0;
unsigned int bin2dec(char *二進文字列){
unsigned int 十進数値 = 0;
int 桁 = 0;
for(int len = strlen(二進文字列)-1;len >= 0 ; len--){
if(二進文字列[len] == '1'){
十進数値 += (1 << 桁); //桁の重み加算
}
桁++ ; //桁上げ
}
return 十進数値 ;
}
■使用例と検算
int main(void) {
//10進数値⇒2進文字列変換
for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
printf("%8x->%s\t",num-1,dec2bin(num-1));
printf("%8x->%s\t",num, dec2bin(num ));
printf("%8x->%s\n",num+1,dec2bin(num+1));
}
//検算:10進数値⇒ 2進文字⇒10進数値(元の数値に戻ればOK)
for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
if(num-1 != bin2dec(dec2bin(num-1))) assert(0);
if(num != bin2dec(dec2bin(num ))) assert(0);
if(num+1 != bin2dec(dec2bin(num+1))) assert(0);
}
}
■コード全部
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
// 16進⇒二進変換表
static char *cnv16to2[] = {
[0] ="0000",[1] ="0001",[2] ="0010",[3] ="0011",
[4] ="0100",[5] ="0101",[6] ="0110",[7] ="0111",
[8] ="1000",[9] ="1001",[0xa]="1010",[0xb]="1011",
[0xc]="1100",[0xd]="1101",[0xe]="1110",[0xf]="1111",
};
// 十進数値⇒二進文字列変換
char *dec2bin(unsigned int x) {
static char output[256];
sprintf(output,
"%s%s%s%s%s%s%s%s",
cnv16to2[(x & 0xF0000000) >> 28],
cnv16to2[(x & 0x0F000000) >> 24],
cnv16to2[(x & 0x00F00000) >> 20],
cnv16to2[(x & 0x000F0000) >> 16],
cnv16to2[(x & 0x0000F000) >> 12],
cnv16to2[(x & 0x00000F00) >> 8],
cnv16to2[(x & 0x000000F0) >> 4],
cnv16to2[(x & 0x0000000F) ]
);
return output ;
}
// 二進文字列⇒十進数値変換
// 1111 = 2^3+2^2+2^1+2^0
// = 1<<3+1<<2+1<<1+1<<0;
// 1010
// = 1<<3+0<<2+1<<1+0<<0;
unsigned int bin2dec(char *二進文字列){
unsigned int 十進数値 = 0;
int 桁 = 0;
for(int len = strlen(二進文字列)-1;len >= 0 ; len--){
if(二進文字列[len] == '1'){
十進数値 += (1 << 桁); //桁の重み加算
}
桁++ ; //桁上げ
}
return 十進数値 ;
}
int main(void) {
//10進数値⇒2進文字列変換
for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
printf("%8x->%s\t",num-1,dec2bin(num-1));
printf("%8x->%s\t",num, dec2bin(num ));
printf("%8x->%s\n",num+1,dec2bin(num+1));
}
//検算:10進数値⇒ 2進文字⇒10進数値(元の数値に戻ればOK)
for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
if(num-1 != bin2dec(dec2bin(num-1))) assert(0);
if(num != bin2dec(dec2bin(num ))) assert(0);
if(num+1 != bin2dec(dec2bin(num+1))) assert(0);
}
}