「マジックナンバー (プログラム)」の版間の差分
編集の要約なし |
|||
13行目: | 13行目: | ||
<!-- ここで提示しているのは、あくまで例題なので、たとえ今後日本の消費税率が8%以外に変更されたとしても、記事およびサンプルコード中の税率をいちいち変更したりしないこと。重要なのは具体的な数値ではなく、概念および説明のほうであることを忘れないこと。 --> |
<!-- ここで提示しているのは、あくまで例題なので、たとえ今後日本の消費税率が8%以外に変更されたとしても、記事およびサンプルコード中の税率をいちいち変更したりしないこと。重要なのは具体的な数値ではなく、概念および説明のほうであることを忘れないこと。 --> |
||
< |
<syntaxhighlight lang="c"> |
||
double calculateTaxIncludedPrice(double price) { |
double calculateTaxIncludedPrice(double price) { |
||
return 1.1 * price; |
return 1.1 * price; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
これは、<code>price</code>に商品の本体価格を入力することで消費税込みの価格が得られる、という計算式を実装する関数である。しかし消費税の税率 (tax rate) は変化し得るため、税率が10%以外に変更されたとき修正が必要となる。このとき「1.1」はマジックナンバーであり「なぜ1.1なのか」という意図が不明瞭である。 |
これは、<code>price</code>に商品の本体価格を入力することで消費税込みの価格が得られる、という計算式を実装する関数である。しかし消費税の税率 (tax rate) は変化し得るため、税率が10%以外に変更されたとき修正が必要となる。このとき「1.1」はマジックナンバーであり「なぜ1.1なのか」という意図が不明瞭である。 |
||
23行目: | 23行目: | ||
ここで、マジックナンバーを取り除くため、名前付きの定数シンボル<code>TaxRate</code>を導入する。 |
ここで、マジックナンバーを取り除くため、名前付きの定数シンボル<code>TaxRate</code>を導入する。 |
||
< |
<syntaxhighlight lang="c"> |
||
double calculateTaxIncludedPrice(double price) { |
double calculateTaxIncludedPrice(double price) { |
||
const double TaxRate = 0.1; |
const double TaxRate = 0.1; |
||
return (1.0 + TaxRate) * price; |
return (1.0 + TaxRate) * price; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
定数シンボルの導入により、式に意図が反映されるため修正が容易になる。 |
定数シンボルの導入により、式に意図が反映されるため修正が容易になる。 |
||
; |
; |
||
< |
<syntaxhighlight lang="c"> |
||
extern void printColorText(const char* text, uint32_t colorValue); |
extern void printColorText(const char* text, uint32_t colorValue); |
||
printColorText("color text", 0x9acd32); |
printColorText("color text", 0x9acd32); |
||
</syntaxhighlight> |
|||
</source> |
|||
この場合、"color text"という文字列が「黄緑色」で表示される。ただし0x9acd32は直感的に「黄緑色」と伝えることは困難なマジックナンバーである。 |
この場合、"color text"という文字列が「黄緑色」で表示される。ただし0x9acd32は直感的に「黄緑色」と伝えることは困難なマジックナンバーである。 |
||
43行目: | 43行目: | ||
マジックナンバーを取り除く手法の一つとして、以下のような書き方がある。 |
マジックナンバーを取り除く手法の一つとして、以下のような書き方がある。 |
||
< |
<syntaxhighlight lang="c"> |
||
const uint32_t YellowGreen = 0x9acd32; |
const uint32_t YellowGreen = 0x9acd32; |
||
printColorText("color text", YellowGreen); |
printColorText("color text", YellowGreen); |
||
</syntaxhighlight> |
|||
</source> |
|||
これらマジックナンバーを避けるため、マジックナンバーが書いてある箇所を[[定数 (プログラミング)|定数]]や[[列挙型]]に置き換えるといった処置がとられる。定数は意味のわかりやすいような名前を付けることができるため、一読して数値の意味を理解できるからである。ここで、定数の初期化の際に右辺値に書かれる数値までマジックナンバーやハードコーディングとは呼ばない。 |
これらマジックナンバーを避けるため、マジックナンバーが書いてある箇所を[[定数 (プログラミング)|定数]]や[[列挙型]]に置き換えるといった処置がとられる。定数は意味のわかりやすいような名前を付けることができるため、一読して数値の意味を理解できるからである。ここで、定数の初期化の際に右辺値に書かれる数値までマジックナンバーやハードコーディングとは呼ばない。 |
||
また、[[1]]や[[0]]はそれ自体が「真」・「偽」などの意味([[真理値]])を示しうる数値であり、マジックナンバーとは呼ばないこともある。ただしC言語では、意味を明確にするため、1/0の数値を直接用いるのではなく、<code>TRUE</code>や<code>FALSE</code>といったシンボルを明示的に定義して利用することがある。 |
また、[[1]]や[[0]]はそれ自体が「真」・「偽」などの意味([[真理値]])を示しうる数値であり、マジックナンバーとは呼ばないこともある。ただしC言語では、意味を明確にするため、1/0の数値を直接用いるのではなく、<code>TRUE</code>や<code>FALSE</code>といったシンボルを明示的に定義して利用することがある。 |
||
< |
<syntaxhighlight lang="c"> |
||
#define TRUE 1 |
#define TRUE 1 |
||
#define FALSE 0 |
#define FALSE 0 |
||
</syntaxhighlight> |
|||
</source> |
|||
== フォーマット識別子 == |
== フォーマット識別子 == |
2020年7月5日 (日) 22:39時点における版
プログラムにおけるマジックナンバー(英: magic number、魔法の数字)とは、何らかの識別子もしくは定数として用いられる、プログラムのソースコード中に書かれた具体的な数値である。そのプログラムを書いた時点では製作者は数値の意図を把握しているが、他のプログラマーまたは製作者本人がマジックナンバーの意図を忘れたときに閲覧すると「この数字の意味はわからないが、とにかくプログラムは正しく動く。まるで魔法の数字だ」という皮肉を含む。
概要
次のような理由で、マジックナンバーはプログラム中に含まれないことが好ましいとされる。
- その数値の持つ意味がわかりづらい。
- 数値を変更する場合に、複数の箇所を変更しなければならない可能性がある。
- 例1
たとえば、消費税が10%の時に、税込価格 (tax-included price) を求める以下のようなソースコードをC言語で書いたとする。
double calculateTaxIncludedPrice(double price) {
return 1.1 * price;
}
これは、price
に商品の本体価格を入力することで消費税込みの価格が得られる、という計算式を実装する関数である。しかし消費税の税率 (tax rate) は変化し得るため、税率が10%以外に変更されたとき修正が必要となる。このとき「1.1」はマジックナンバーであり「なぜ1.1なのか」という意図が不明瞭である。
ここで、マジックナンバーを取り除くため、名前付きの定数シンボルTaxRate
を導入する。
double calculateTaxIncludedPrice(double price) {
const double TaxRate = 0.1;
return (1.0 + TaxRate) * price;
}
定数シンボルの導入により、式に意図が反映されるため修正が容易になる。
extern void printColorText(const char* text, uint32_t colorValue);
printColorText("color text", 0x9acd32);
この場合、"color text"という文字列が「黄緑色」で表示される。ただし0x9acd32は直感的に「黄緑色」と伝えることは困難なマジックナンバーである。
マジックナンバーを取り除く手法の一つとして、以下のような書き方がある。
const uint32_t YellowGreen = 0x9acd32;
printColorText("color text", YellowGreen);
これらマジックナンバーを避けるため、マジックナンバーが書いてある箇所を定数や列挙型に置き換えるといった処置がとられる。定数は意味のわかりやすいような名前を付けることができるため、一読して数値の意味を理解できるからである。ここで、定数の初期化の際に右辺値に書かれる数値までマジックナンバーやハードコーディングとは呼ばない。
また、1や0はそれ自体が「真」・「偽」などの意味(真理値)を示しうる数値であり、マジックナンバーとは呼ばないこともある。ただしC言語では、意味を明確にするため、1/0の数値を直接用いるのではなく、TRUE
やFALSE
といったシンボルを明示的に定義して利用することがある。
#define TRUE 1
#define FALSE 0
フォーマット識別子
マジックナンバーは、データ構造体の中にある本質的な意味を持たない数値を指すことがある。これはデータ構造体を識別し、間違った型として扱われる事を防ぐために使われる。これについてはフォーマット識別子としてのマジックナンバーを参照。
関連用語
プログラムに直接書き込んでしまう具体的な値は数値に限らない。特定のファイルのフルパスを表す文字列を埋め込むこともままある。
このようにマジックナンバーを含めてプログラムに決め打ちの値を埋め込むことを、ハードコーディングと言う。