Skip to content

Instantly share code, notes, and snippets.

@watasuke102
Last active December 17, 2020 09:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save watasuke102/0c893d97dc779c8dbeef8adc2e893a49 to your computer and use it in GitHub Desktop.
Save watasuke102/0c893d97dc779c8dbeef8adc2e893a49 to your computer and use it in GitHub Desktop.
C言語で10進数→2進数を変換する(C++版は下)
/* 10進数→2進数変換 */
// 入力が1,048,576未満の場合に正常に動作する
// ちなみに入力が524,288を越えるとansの値の表示(printf)がおかしくなる
// なんでこうなるのかはわからなかったです、だれかたすけてください
/// <計算の考え>
/// inputを2でわったあまりをansの左に追加する
/// (10のi乗をかけることによって、左に追加していく
/// 例えば、10の一番左の桁に1を追加するには、100を足せば良い)
/// このとき、例えば0d4 (0b100)のような表現をしたい時、
/// 左に足していくと「00」を表現する方法がない
/// そのため、すべての位に1を足しておき、あとで足した分を引く
/// (例: 0d15 [0b1111] は2222としておき、最後に1111を引く
/// 0d5 [0b101] は 212としておき、最後に 111を引く)
#include <stdio.h>
// 実質 #define, llをunsigned long longに置き換えることができる
// unsigned long longの説明は後で
typedef unsigned long long ll;
// 10のn乗を返す関数
// pow_10th(n)と書くと、実行するときに「pow_10th(n)」の部分が
// まるごと10のn(関数のカッコの中に入れた数字)乗の数字に置き換わると見てOK
// 例: pow_10th(0) -> 1 (に置き換わる)
// pow_10th(1) -> 10
// pow_10th(2) -> 100
ll pow_10th(int cnt)
{
if (cnt == 0) return 1;
ll ans = 10;
for (int i = 0; i < (cnt-1); i++) ans *= 10;
return ans;
}
int main() {
ll input = 0;
printf("input: "); scanf("%llu", &input);
//int input = 0;
//printf("input: "); scanf("%d", &input);
//printf("[debug] input: %d\n", input);
// (以下、わかりやすいように2進数は4桁毎に半角スペースを入れる)
// 例えば入力が65536だった場合、2進数では1 0000 0000 0000 0000になる
// 流石に大きすぎてint型の変数に入らないので、
// クソデカunsigned long longを使う (typedefによってllに置き換えられている)
// unsignedは「負の数を扱えない変数にする」という意味、その分保存できる正の数が増える
// unsigned intは32ビット(4バイト)、2進数で1111 1111 1111 1111 1111 1111 1111 1111(10進数で4,294,967,295)までしか保存できない
// unsigned long longは64ビット(8バイト)なので、1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
// すなわち10進数で18,446,744,073,709,551,615まで保存可能
// ここらへん詳しくないので間違ってたらごめんね
// 参考: https://docs.microsoft.com/ja-jp/cpp/cpp/data-type-ranges?view=msvc-160
ll ans = 0;
int i = 0;
// 2で割ったあまりを数字の左に追加していく
while (input >= 1) {
ans += ((input % 2) + 1) * pow_10th(i);
input /= 2;
i++;
}
// 全ての位に余分に1足されているため、それを取り除く
ll extra = 0;
for (int j = 0; j < i; j++) {
// extra=0のとき、extra*10 + 1 = 1
// extra=1のとき、extra*10 + 1 = 11
extra *= 10;
extra += 1;
}
// 答えを出力して、終わり
// lluはunsigned long longを正常に表示させるためのもの
printf("0b%llu\n", ans-extra);
return 0;
}
/// 実行例 []で囲まれたものは入力とする
/// (例1)
/// input: [0]
/// 0b0
/// (例2)
/// input: [15]
/// 0b1111
/// (例3)
/// input: [65536]
/// 0b10000000000000000
/// (例3)
/// input: [1048575]
/// 0b11111111111111111111
/* 10進数→2進数変換 - C++版 */
// 入力が18,446,744,073,709,551,616未満の場合に正常に動作する
// C言語でかなり頑張って1,048,576未満まで入力できるようにしたのに、
// C++で書いたら5分で18,446,744,073,709,551,616未満まで対応できる
// プログラムが書ける世界、かなしいね
/// <計算の考え>
/// inputを2でわって出たあまりの数字を「文字」として、文字列型の変数に追加していく
/// 基本的に文字列の右に追加されるので、表示する前に文字列を反転させる
/// 文字として扱うので、割ったあまりが0の場合も何も気にせず書ける
#include <iostream>
#include <sstream>
#include <algorithm>
typedef unsigned long long ll;
int main() {
ll input;
// C++の標準出力 (ちょっと違うけどprintfのようなもの)
std::cout << "input: ";
// C++の標準入力 (scanfのようなもの)
std::cin >> input;
// 計算結果を文字列に追加していくためにこれを使う
std::ostringstream ans;
// 2で割ったあまりの数字を文字として扱い、文字列に追加していく
while(input >= 1) {
ans << input % 2;
input /= 2;
}
// 右に追加していったので、反転させる
std::string ans_str = ans.str();
std::reverse(ans_str.begin(), ans_str.end());
// 答えを出力して、おわり
std::cout << "0b" << ans_str << std::endl;
return 0;
}
@watasuke102
Copy link
Author

extraいらなかったなこれ

<略>
while (input >= 1) {
  ans += (input % 2) * pow_10th(i);
  input /= 2;
  i++;
}
printf("0b%llu\n", ans);
return 0;

@toge
Copy link

toge commented Dec 15, 2020

unsigned intは32ビット(4バイト)、2進数で1111 1111 1111 1111(10進数で65,535)までしか保存できない
32ビット(4バイト)ならば、1111 1111 1111 11111 1111 1111 1111 11111(10進数で4,294,967,295)じゃないですかね。
65,535は16ビット(2バイト)のunsignedの最大値になると思います。

@watasuke102
Copy link
Author

unsigned intは32ビット(4バイト)、2進数で1111 1111 1111 1111(10進数で65,535)までしか保存できない
32ビット(4バイト)ならば、1111 1111 1111 11111 1111 1111 1111 11111(10進数で4,294,967,295)じゃないですかね。
65,535は16ビット(2バイト)のunsignedの最大値になると思います。

本当だ・・・なんかおかしいと思った・・・
ありがとうございます・・・

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment