C#

大字に変換

コーディング

/// <summary>
/// 数字を大字に変換します。
/// </summary>
/// <param name="Value">変換する数字を指定します。</param>
/// <returns></returns>
/// <remarks>Copyright (C) 2021, Kaigo, hesperus.net</remarks>
public static string ToDaiji(string Value)
{
    // チェック

    if ((Value == null) || (Value.Length == 0))
    {
        return string.Empty;
    }

    if (Value.Length > (1 << 22))
    {
        throw new ArgumentException("文字列が長すぎます。", "Value");
    }

    foreach (char c in Value)
    {
        if ((c < '0') || (c > '9'))
        {
            throw new ArgumentException("数字以外の文字が含まれています。", "Value");
        }
    }


    // 4桁を1処理単位にする。
    // Unitsには対象の文字列部分のインデックスと長さを、
    // それぞれビット4~30とビット0~3に入れて保存する。

    int[] Units = new int[22]; // 88桁÷4桁=22処理単位
    int UnitIndex = 0;

    {
        int FirstIndex = -1;

        for (int i = 0; i < Value.Length; i++)
        {
            char c = Value[i];

            if (c != '0')
            {
                FirstIndex = i;
                break;
            }
        }

        if (FirstIndex < 0)
        {
            return "零";
        }

        if (Value.Length - FirstIndex > 88)
        {
            return "無量大数";
        }


        int FirstLimit = FirstIndex + 4;
        int n = Value.Length;

        while (n > FirstLimit)
        {
            Units[UnitIndex++] = ((n -= 4) << 4) | 4;
        }

        if (n > FirstIndex)
        {
            Units[UnitIndex++] = (FirstIndex << 4) | (n - FirstIndex);
        }
    }


    StringBuilder Builder = new StringBuilder();
    bool HasAppended = false;


    // 大字の数字
    char[] DaijiNumbers = { '壱', '弐', '参', '四', '伍', '六', '七', '八', '九' };

    // 大字の単位 その1
    char[] DaijiUnits_1 = { '拾', '佰', '阡' };

    // 4桁を処理するサブルーチン
    Action ProcessUnit = delegate
    {
        int Unit = Units[--UnitIndex];
        int Index = Unit >> 4;
        int Length = Unit & 0x0f;

        HasAppended = false;

        for (int i = 0; i < Length; i++)
        {
            char c = Value[Index++];

            if (c == '0')
            {
                // 0を処理しない
                continue;
            }

            Builder.Append(DaijiNumbers[c - '1']);

            int n = Length - i - 2;

            if (n >= 0)
            {
                Builder.Append(DaijiUnits_1[n]);
            }

            HasAppended = true;
        }
    };


    // 大字の単位 その2
    char[] DaijiUnits_2 = { '萬', '億', '兆', '京', '垓', '杼', '穣', '溝', '澗', '正', '載' };

    // 大字の単位 その3
    string[] DaijiUnits_3 = { "極", "恒河沙", "阿僧祇", "那由他", "不可思議" };

    while (true)
    {
        ProcessUnit();

        if (UnitIndex == 0)
        {
            return Builder.ToString();
        }

        if (!HasAppended)
        {
            continue;
        }

        if (UnitIndex < 12)
        {
            Builder.Append(DaijiUnits_2[UnitIndex - 1]);
            continue;
        }

        if ((UnitIndex & 1) != 0)
        {
            Builder.Append(DaijiUnits_2[0]);
            ProcessUnit();
        }

        Builder.Append(DaijiUnits_3[(UnitIndex - 12) >> 1]);
    }
}

大字の表記

数字 漢数字 大字
0
1
2
3
4
5
6
7
8
9
10
100
1000
10000

※通常使用する表記を記載した。

漢数字の単位

100 101 102 103

まん
104 105 106 107

おく
108 109 1010 1011

ちょう
1012 1013 1014 1015

けい
1016 1017 1018 1019

がい
1020 1021 1022 1023

じょ
1024 1025 1026 1027
※正しくは「禾」へんに「予」

じょう
1028 1029 1030 1031

こう
1032 1033 1034 1035

かん
1036 1037 1038 1039

せい
1040 1041 1042 1043

さい
1044 1045 1046 1047

ごく
1048 1049 1050 1051
1052 1053 1054 1055
恒河沙
ごうがしゃ
1056 1057 1058 1059
1060 1061 1062 1063
阿僧祇
あそうぎ
1064 1065 1066 1067
1068 1069 1070 1071
那由他
なゆた
1072 1073 1074 1075
1076 1077 1078 1079
不可思議
ふかしぎ
1080 1081 1082 1083
1084 1085 1086 1087
無量大数
むりょうたいすう
1088
※1088以上は無量大数

「不可思議」のような8桁を使う単位では、「21万6千不可思議」のように「万」を使って上位4桁が表現されるらしい。

123456789

下位から4桁ずつに分ける。

Index
0 6789
1 2345
2 1

上位から処理していく。

Index = 2
1
Index = 1
2 3 4 5
弐阡 参佰 四拾
Index = 0
6 7 8 9
六阡 七佰 八拾

連結する。

壱 億 弐阡 参佰 四拾 伍 萬 六阡 七佰 八拾 九

4桁の数字を処理するルーチンを作って、単位と組み合わせればできそうだ。

(2021/02/18 初稿)