このページでは、値から特定の桁のみを取得する方法について解説していきます。
この方法を知っておけば、例えば下記のように任意の値から特定の桁のみを取得することができるようになります。
123456
から1
〜3
桁目を取得:345
123456
から0
〜0
桁目を取得:6
最初は自然数に対して解説していきますが、後ほど小数点以下の桁を指定して取得する方法や、2進数や8進数で考えた場合の取得方法についても解説していきたいと思います!
Contents
自然数から特定の桁のみを取得する
では、特定の桁のみを取得する方法について解説していきます。
今後の説明が曖昧にならないように、まずは言葉の定義から整理していきたいと思います。
このページでは、1の位を 0
桁目として解説していきたいと思います。そして、この 0
桁目を基準として、そこから左側の桁ほど大きな桁、右側の桁ほど小さな桁として扱っていきたいと思います。
例えば10の位であれば 1
桁目、100の位であれば 2
桁目、小数第1位(10分の1の位)は -1
桁目、小数第2位(100分の1の位)は -2
桁目といった感じになります。
ですので、123.456
の値の -2
桁目から 1
桁目のみを取得した場合、結果は 2345
になることになります。
自然数から特定の桁のみを取得する方法
では、ここからは値から取得する桁を m
桁目 〜 n
桁目(m ≦ n
)として解説していきたいと思います。
まずは自然数(0
を含めた自然数)から特定の桁のみを取得する方法を解説していきます。
自然数から m
桁目 〜 n
桁目を取得するためには下記の3つの処理を行えば良いです。
- 値を
10
のn + 1
乗で剰余算する - 1. の結果を
10
のm
乗で除算する - 2. の結果の小数点以下を切り捨てる
値を 10
の n + 1
乗で剰余算することで、その値の 0
桁目 〜 n
桁目のみを取得することができます。
さらにその結果に対して 10
の m
乗の値で除算すれば、除算前に比べて各桁が右側(小さい方)に m
桁分シフトすることになります。つまり、m
桁目 〜 n
桁目のみが整数部に残ることになります(0
桁目 〜 m - 1
桁目は小数部に移動する)。
ですので、後はその結果の小数点以下を切り捨ててやれば、元々の値の m
桁目 〜 n
桁目のみを取得した結果を得ることができます。
ここで説明した下記の3つを利用すれば、小数点以下の特定の桁の取得や、10進数以外の進数の値の特定の桁の取得も行うことができます。
- 剰余算
- 桁のシフト
- 小数点以下の切り捨て
スポンサーリンク
自然数から特定の桁のみを取得する関数
上記のように処理を行なって自然数から特定の桁のみを取得する関数は、下記における getDigits
のように記述することができます。
#include <stdio.h>
#include <math.h> /* pow */
/*****************************
* valueのm桁目からn桁目を取得する
* value:取得先となる自然数
* m:取得を開始する桁
* n:取得を終了する桁
* 返却値:取得した桁(整数)
* ****************************/
int getDigits(int value, int m, int n) {
int mod_value;
int result;
/* n桁目以下の桁を取得 */
mod_value = value % (int)pow(10, n + 1);
/* m桁目以上の桁を取得 */
result = mod_value / pow(10, m);
return result;
}
int main(void) {
int result;
/* 123456の3桁目〜4桁目を取得する */
result = getDigits(123456, 3, 4);
printf("%d\n", result);
return 0;
}
第1引数 value
に桁の取得先となる自然数を指定し、さらに第2引数 m
と第3引数 n
で取得したい桁を指定して getDigits
を実行すれば、value
の m
桁目 〜 n
桁目のみの値を戻り値として取得することができます。
getDigits
関数で使用している pow
は、第1引数の値を第2引数の値で冪乗する関数になります。pow
を使用する際は math.h
をインクルードする必要があります。
pow
の返却値は double
型の浮動小数点数であることに注意してください。
剰余算を行う %
演算子では、左辺と右辺の値の両方が整数である必要があります。ですので、剰余算を行うときに下記のように記述してしまうと、右辺が浮動小数点数の値になるのでコンパイル時にエラーが発生します。
mod_value = value % pow(10, n + 1);
このエラーが発生しないように、上記の getDigits
では pow
関数の結果を int
型でキャストしてから剰余算を行うようにしています((int)pow(10, n+1)
と記述すれば、pow
関数の結果が int
型として扱われる)。
また、前述で紹介した切り捨て処理を行なっている箇所がありませんが、C言語
では 整数 / 整数
の結果は自動的に小数点以下が切り捨てられた整数となりますので、mod_value / (int)pow(10, m)
の処理で自動的に小数点以下が切り捨てられていることになります。
負の整数から特定の桁のみを取得する関数
もし負の整数も扱えるようにしたいのであれば、その負の整数の絶対値を求めてから特定の桁を取得するようにしていけば良いです。
絶対値を取得する方法については下記ページでまとめていますので詳しく知りたい方は下記ページ後を参照いただければと思います。
【C言語】絶対値を求める方法(abs関数の利用・関数使わない・マクロなど)要は、int
型の変数の絶対値は abs
関数により算出できますので、下記のように事前に abs
関数で絶対値を求めてから計算を行なっていくようにすれば良いです(abs
関数を使用するには stdlib.h
をインクルードする必要があります)。
/*****************************
* valueのm桁目からn桁目を取得する
* value:取得先となる整数
* m:取得を開始する桁
* n:取得を終了する桁
* 返却値:取得した桁(整数)
* ****************************/
int getDigits(int value, int m, int n) {
int mod_value;
int result;
/* 絶対値を求める */
value = abs(value);
/* n桁目以下の桁を取得 */
mod_value = value % (int)pow(10, n);
/* m桁目以上の桁を取得 */
result = mod_value / pow(10, m - 1);
return result;
}
小数点以下も含めて取得する
では、次は小数点以下も含めて特定の桁を取得する方法について解説していきます。
スポンサーリンク
小数点以下も含めて特定の桁のみを取得する方法
考え方は自然数の時と同様で、m
桁目 〜 n
桁目のみを取得したい場合、下記の3つの処理を行えば良いです。
- 値を
10
のn + 1
乗で剰余算する - 1. の結果を
10
のm
乗で除算する - 2. の結果の小数点以下を切り捨てる
ただし、今回は小数点以下の値も扱うため、桁の取得先となる値は浮動小数点数である必要があります(先程紹介した getDigits
関数の第1引数 value
が double
型 or float
型となる)。
さらに、%
演算子では浮動小数点数に対する剰余演算を行うことはできません。これを行うとコンパイル時にエラーになります。
したがって、下記のように単に getDigits
関数の第1引数 value
をdouble
型や float
型に変えるだけだとコンパイル時にエラーが出てしまいます(value
に対して剰余演算子を使ってはダメ)。
int getDigits(double value, int m, int n) {
int mod_value;
int result;
/* n桁目以下の桁を取得 */
mod_value = value % (int)pow(10, n + 1);
/* m桁目以上の桁を取得 */
result = mod_value / pow(10, m);
return result;
}
ですので、今回の場合、そのまま %
演算子を使うのは NG です。
C言語
においては、浮動小数点数に対して剰余算を行うための関数 fmod
が存在するので、今回はこの関数を利用して剰余算を行なっていきたいと思います。
ただ、fmod
関数の場合、浮動小数点数の誤差によって思わぬ結果が算出されることがあるので注意が必要です(本当であれば整数化してから剰余演算子 %
により剰余算を求める方が良い)。
この辺りの解説は下記ページで解説していますので、詳しく知りたい方は下記ページを参照していただければと思います。
【C言語】浮動小数点数に対して剰余演算を行う方法(fmodや自力で演算など)剰余算をfmod
関数で行うようにすれば、あとは自然数の時と同様に下記を実行するだけで、小数点以下も含めた特定の桁の取得を行うことができるようになります。
- 値を
10
のn + 1
乗で剰余算する - 1. の結果を
10
のm
乗で除算する - 2. の結果の小数点以下を切り捨てる
小数点以下も含めて特定の桁のみを取得する関数
以上の解説を踏まえて特定の桁の取得を行う関数は、下記の getDigits
関数のように記述することができます。
#include <stdio.h>
#include <math.h> /* pow */
/*****************************
* valueのm桁目からn桁目を取得する
* value:取得先となる浮動小数点数
* m:取得を開始する桁
* n:取得を終了する桁
* 返却値:取得した桁(整数)
*****************************/
int getDigits(double value, int m, int n) {
double mod_value;
int result;
/* 事前に絶対値を求めておく */
value = fabs(value);
/* n桁目以下の桁を取得 */
mod_value = fmod(value, pow(10, n + 1));
/* m桁目以上の桁を取得 */
result = mod_value / pow(10, m);
return result;
}
int main(void) {
int result;
result = getDigits(54321.123, -2, 3);
printf("%d\n", result);
return 0;
}
getDigits
関数の第1引数 value
には浮動小数点数を指定することが可能になっていますが、そのほかの関数の使用方法等は 自然数から特定の桁のみを取得する関数 と同じです。
また、上記の getDigits
関数では負の浮動小数点数も扱えるように、第1引数 value
を fabs
関数により絶対値に変換してから、特定の桁の取得を行う処理を開始するようにしています。
他の進数で考えた場合の特定の桁のみを取得する
最後に、10進数の値を他の進数で考えた場合の特定の桁を取得する方法について解説していきます。
例えば10進数の 345
は2進数表記では下記のようになります。
101011001
この時の 3
桁目 〜 6
桁目を取得した場合の結果は下記のようになります(桁の数え方は 自然数から特定の桁のみを取得する の最初で説明した通りとします)。
1011
また、10進数の 54321
は16進数表記では下記のようになります。
D431
この時の 2
桁目 〜 3
桁目を取得した場合の結果は下記のようになります。
D4
スポンサーリンク
他の進数で考えた場合の特定の桁のみを取得する方法
なんだか難しそうですが、実は 自然数から特定の桁のみを取得する で紹介した自然数から特定の桁のみを取得する方法とほぼ同様の手順でこれらを実現することができます。
10進数の自然数から m
桁目 〜 n
桁目のみを取得したい場合は下記の3つの処理を行う必要がありました。
- 値を
10
のn + 1
乗で剰余算する - 1. の結果を
10
のm
乗で除算する - 2. の結果の小数点以下を切り捨てる
これに対し、10進数の自然数を他の進数(その進数を B
進数とします)で考えた時の m
桁目 〜 n
桁目のみを取得したい場合に行う処理は下記の通りになります。
- 値を
B
のn + 1
乗で剰余算する - 1. の結果を
B
のm
乗で除算する - 2. の結果の小数点以下を切り捨てる
- 3. の結果を
B
進数表記にする
1. と 2. の処理に関しては、10進数から特定の桁のみを取得する場合に 10
の冪乗の値を用いて行なっていたところを B
の冪乗の値を用いるように変更すれば良いだけです。
さらに、3. の処理は10進数の自然数から特定の桁のみを取得する場合と全く同じになります。
これはつまり、値を B
の n + 1
乗で剰余算を行うということは、B
進数表記した値の 0
桁目 〜 n
桁目のみを取得する処理と同等であり、さらに剰余算結果に対して B
の m
乗で除算を行って小数点以下を切り捨てるということは、B
進数表記した値の m
桁目 〜 n
桁目のみを取得する処理と同等であると考えることができることを意味します。
ただし、上記の処理で取得できる値は10進数の値になるので、最後に 4. で、それを B
進数表記に変換する必要があります。
この方法については下記ページで解説していますので、10進数の値を他の進数に変換する方法を詳しく知りたい方は下記ページを参照していただければと思います。
おそらく下記ページを読んでいただければ、B
進数に関しても剰余算と除算により特定の桁が取得できるメカリズムを理解していただけると思います(下記ページでは B
進数を N
進数と読んでいるので注意してください)。
ここでは、上記ページの プログラムのソースコード で紹介している DectoN
関数を使用して、10進数の値を特定の進数表記に変換することとしたいと思います。
DectoN
関数を利用する場合、下記の配列や関数等も必要になるので、必要に応じてこれらも上記ページの プログラムのソースコード からコピペしてください。
- 関数
reverse
- 配列
coef
他の進数で考えた場合の特定の桁のみを取得する関数
ここまでの解説を踏まえて作成した、他の進数で考えた場合の特定の桁のみを取得する関数は下記の getDigits
になります。
#include <stdio.h>
#include <math.h> /* pow */
#include <stdlib.h> /* abs */
/* unsigned intのビット数 */
#define MAX_NUM_DIGITS 32
/* 係数を文字に変換するテーブル */
const char coef[36] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
};
/* num文字の文字列の並びを逆順にする */
void reverse(char ans[], int num) {
int i;
char tmp;
for (i = 0; i < num / 2; i++) {
tmp = ans[i];
ans[i] = ans[num - 1 - i];
ans[num - 1 - i] = tmp;
}
}
/* 10進数decをn進数に変換して結果をansに格納する */
void DectoN(char ans[], unsigned int dec, unsigned int n) {
unsigned int i;
unsigned int digit_num;
if (n > 36 || n < 2) {
/* 対応しているのは2進数から36進数まで */
return;
}
i = 0;
while (dec > 0) {
/* i桁目の係数を求める */
digit_num = dec % n;
/* 文字に変換 */
ans[i] = coef[digit_num];
/* n進数で1桁分桁下げ */
dec = dec / n;
/* 次に求める係数の桁 */
i++;
}
/* 最後にヌル文字をつける */
ans[i] = '\0';
/* 文字列の並びを逆順にする */
reverse(ans, i);
}
/*****************************
* valueのm桁目からn桁目を取得する
* ans:取得した桁を格納する配列
* value:取得先となる整数
* m:取得を開始する桁
* n:取得を終了する桁
* base:基数
* ****************************/
void getDigits(char ans[], int value, int m, int n, unsigned int base) {
int mod_value;
unsigned int result;
unsigned int unsigned_value;
/* 負の値は正の値に変換 */
unsigned_value = abs(value);
/* n桁目以下の桁を取得 */
mod_value = unsigned_value % (int)pow(base, n + 1);
/* m桁目以上の桁を取得 */
result = mod_value / pow(base, m);
/* 取得した桁をbase進数に変換 */
DectoN(ans, result, base);
}
int main(void) {
int result;
char ans[MAX_NUM_DIGITS + 1];
getDigits(ans, 54321, 2, 3, 16);
printf("%s\n", ans);
return 0;
}
引数や返却値が 自然数から特定の桁のみを取得する関数 で紹介した getDigits
関数のものとは異なるので注意してください。
この getDigits
関数での変換結果は文字列になります。これは、10進数を超える進数の場合、文字を扱う必要があるためです。
そのため、その変換結果の文字列を格納するための配列を第一引数の ans
で受け取るようにしています。
また引数 base
により、どの進数に変換するのかを関数実行側から指定できるようにしています。
例えば引数 base
が 16
であれば16進数に変換した結果が ans
に格納されることになります。
関数内で行なっている処理は主に下記の4つになります(負の整数も扱えるように事前に abs
関数の実行も行っています)。
- 値を
B
のn + 1
乗で剰余算する - 1. の結果を
B
のm
乗で除算する - 2. の結果の小数点以下を切り捨てる
- 3. の結果を
B
進数表記にする
4. に関しては前述の DectoN
関数を利用して行なっています。この関数の中で、第1引数 ans
に 3. の結果を引数 base
で指定された進数に変換した結果が格納されます。
DectoN
関数では、変換先の進数は2進数から36進数のみとなりますので、getDigits
関数に関しても base
が 2
〜 36
以外の場合は桁の取得が出来ないので注意してください。
また、DectoN
関数が使用している reverse
や coef
に関しては、前述の通り下記ページの プログラムのソースコード で紹介しているものになります。
まとめ
このページでは、値の特定の桁のみを取得する方法について解説しました!
特定の桁の取得先としては、主に「自然数のみ」「小数点以下も含めて」「10進数以外」のパターンについて解説しましたが、いずれにおいてもポイントになるのが除算と剰余算です。
基数(B
進数における B
の値)の冪乗による除算を行うことで、値の各桁をシフトさせて不要な桁を整数部から追い出したり必要な桁を整数部に移動することができます。
今回は除算を中心に解説しましたが、乗算でも同様に桁のシフトを行うことが可能です。
また剰余算を行うことで 0
桁目から必要な桁のみを取得するようなことも可能です。逆に考えれば、剰余算では不要な桁を全て 0
にする処理とも捉えることができます。
例えば前述でも紹介した下記ページでの “10進数から N 進数への変換” も、結局は上記の考え方を応用したものになります。
【C言語】10進数をN進数に変換するこのあたりの除算(もしくは乗算)によるシフトや剰余算による不要な桁を 0
にするような使い方はいろんなところで活躍しますので、是非覚えておいてください!
オススメの参考書(PR)
C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!
まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。
- 参考書によって、解説の仕方は異なる
- 読み手によって、理解しやすい解説の仕方は異なる
ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?
それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。
なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。
特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。
もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!
入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。
https://daeudaeu.com/c_reference_book/