数式での翻訳 |
---|
\(n \in \mathbb{N} \setminus \{0\}\)に対し、記号\(\textrm{♭}\)および\(\textrm{♯}\)のみからなる長さ\(n\)の文字列をそれぞれ\(\textrm{♭}^n\)と\(\textrm{♯}^n\)で表し、空文字列を\(\textrm{□}\)と置きます。記号\(\textrm{♭}\)と\(\textrm{♯}\)のみからなる文字列の集合 \[ \textrm{HenKaKiGou} = \{\textrm{♭}^n \mid n \in \mathbb{N} \setminus \{0\}\} \cup \{\textrm{□}\} \cup \{\textrm{♯}^n \mid n \in \mathbb{N} \setminus \{0\}\} \] に属する文字列を変化記号と呼びます。定義から、変化記号には可算無限種類の文字列があります。例えば\(\textrm{♭}\textrm{♭}\)や\(\textrm{♯}\textrm{♯}\textrm{♯}\)は変化記号ですが、\(\textrm{♭}\textrm{♯}\)や\(\textrm{♯}\textrm{♭}\)は変化記号ではありません。完全に公理的集合論で定義をしたい場合は、記号を以下の規則で自然数にコードすることで、\(\mathbb{N}\)を記号の集合とする文字列の集合に翻訳して下さい。 \[ \begin{align} \textrm{♭} & := 0 \\
\textrm{♯} & := 1 \end{align} \] 通常の流儀では空文字列を変化記号と呼ぶことはしないと思いますが、今回は実装の便宜上空文字列を変化記号とみなしています。また流儀によっては\(\textrm{??}\)(環境によっては正しく表示できません)や\(\textrm{?}\)や\(\textrm{??}\)(環境によっては正しく表示できません)を変化記号として用いますが、ここではそれらを用いません。
また写像 \[ \begin{align} \textrm{GetNum} \colon \textrm{HenKaKiGou} & \to \mathbb{Z} \\
S & \mapsto \textrm{GetNum}(S) \end{align} \] を以下のように定めます:
- \(S = \textrm{♭}^n\)を満たす\(n \in \mathbb{N} \setminus \{0\}\)が存在するならば、\(\textrm{GetNum}(S) = -n\)である。
- \(S = \textrm{□}\)ならば、\(\textrm{GetNum}(S) = 0\)である。
- \(S = \textrm{♯}^n\)を満たす\(n \in \mathbb{N} \setminus \{0\}\)が存在するならば、\(\textrm{GetNum}(S) = n\)である。
この写像\(\textrm{GetNum} \colon \textrm{HenKaKiGou} \to \mathbb{Z}\)は全単射であるので、これを通じて\(\textrm{HenKaKiGou}\)に環構造を誘導します。ちなみに幹音の記事において定義した写像\(\textrm{KanOn} \to \mathbb{Z}/7 \mathbb{Z}\)もまた\(\textrm{GetNum}\)と表していましたが、\(\textrm{KanOn} \cap \textrm{HenKaKiGou} = \emptyset\)であるため、このような記法の重複による曖昧さはあまり問題を起こしません。このように記法を重複させることをオーバーロードと言い、数学において曖昧さが致命的でない範囲で断りなく多用されるものですので、今後も断りなく使っていきます。
C++での宣言 |
---|
変化記号のクラスおよび関係する関数たちを以下のように宣言します。
class HenKaKiGou
{
private:
int m_num;
public:
inline HenKaKiGou( const int& num ) noexcept;
HenKaKiGou& operator++() noexcept;
HenKaKiGou& operator--() noexcept;
inline string Display() const noexcept;
inline const int& GetNum() const noexcept;
static string IntToString( const int& num ) noexcept;
};
inline bool operator==( const HenKaKiGou& S1 , const HenKaKiGou& S2 ) noexcept;
inline bool operator!=( const HenKaKiGou& S1 , const HenKaKiGou& S2 ) noexcept;
inline HenKaKiGou operator+( const HenKaKiGou& S1 , const HenKaKiGou& S2 ) noexcept;
inline HenKaKiGou operator-( const HenKaKiGou& S1 , const HenKaKiGou& S2 ) noexcept;
C++での定義 |
---|
実際の実装例についてはこちらをご覧下さい。実装においては以下の仕様を要請します。
inline HenKaKiGou::HenKaKiGou( const int& num ) noexcept
はメンバ初期化子リストm_S( IntToString( num ) )
,m_num( num )
で定める。HenKaKiGou& HenKaKiGou::operator++() noexcept
とHenKaKiGou& HenKaKiGou::operator--() noexcept
はそれぞれm_num += 1
とm_num -= 1
を実行し、return *this
と定める。inline string HenKaKiGou::Display() const noexcept
はreturn IntToString( m_num )
と定める。inline const int& HenKaKiGou::GetNum() const noexcept
はreturn m_num
と定める。static string HenKaKiGou::IntToString( const int& num )
はnum == 0
ならば空文字列を、num > 0
ならば"♯"
のみからなる長さ-num
の文字列を、num < -1
ならば"♭"
のみからなる長さnum
の文字列を返す。- クラス
HenKaKiGou
に対する等号演算子は自然なものである。 - クラス
HenKaKiGou
に対する加法演算子と減法演算子は、HenKaKiGou::GetNum()
が加法演算子と減法演算子と可換になるように定める。