質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

JavaScript:正規表現を使わずに半角数字を漢数字に変換したい

受付中

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,989
退会済みユーザー

退会済みユーザー

前提・実現したいこと

JavaScriptで"正規表現を使わず"に、テキストエリアに入力された
半角数字を漢数字に変換し、入力欄の下に表示したい。

該当のソースコード

<section>
  <p>数字を入力してください。漢数字に変換します。</p>
  <form>
    <input type="text" id="num"/>
    <input type="button" value="変換" onclick="convert()"/>
  </form>
  <p id="result">ここに結果を表示します。</p>
</section>
function toKanji(n) {
  var th = ["","千","二千","三千","四千","五千","六千","七千","八千","九千"];
  var  h = ["","百","二百","三百","四百","五百","六百","七百","八百","九百"];
  var  t = ["","十","二十","三十","四十","五十","六十","七十","八十","九十"];
  var  o = ["","一","二","三","四","五","六","七","八","九"];
  var str = '';
  var s = '';
 var m = '';

  if (n == 0) {
    return '零';
  } else if (n < 0 || isNaN(n)) {
    return alert('漢数字に変換できません。');
  } else { 
    for (var i = 0; i < n.length; i++) {
    s = n.substr(,); //

    th = th [ Math.floor(s / 1000) ];
    h = h [ Math.floor(s / 100) % 10 ];
    t = t [ Math.floor(s / 10) % 10 ];
    o = o [ s % 10 ];
    m = th + h + t + o ;
    str += m ;
    }
    return str;
  }
}

function convert() {
  var n = document.getElementById('num').value;
  var result = document.getElementById('result');
  result.innerHTML = toKanji(n);
}

補足情報(言語/FW/ツール等のバージョンなど)

文系の学生です。独学でJavaScriptを勉強をしています。
上記のHTMLを元に色々試してみたのですが、全然できなくて悩んでおります。

ルールとして、下記の事項を守ること。
1)桁は 一、十、百、千、万、億、兆、京・・・・無量大数 まで。
2)一万未満の千の位には、常に一は表示しない。
3)一万以上の4桁区切り内での千の位は、一千丁度のときだけ一を表示する。

123456789 = 一億二千三百四十五万六千七百八十九
10010000 = 千一万
10001 = 一万一
1001 = 千一

どうすればできるのか考えてみたのですが、
4桁ずつ切り出し漢数字へ変換
→4桁ごとに桁を追加
→if文で4桁の中身が空欄だったら桁つけない?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2017/08/01 12:54

    質問文のコードはコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。ご自身で試されたコードを質問文に追記し、「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを具体的に追記されたほうが回答が望めると思います。

    キャンセル

  • yambejp

    2017/08/01 13:00

    要求定義ができているなら実装するだけですよね?むしろ何がわからないでしょう?具体的にソースを例示してつまっているところを教えてください

    キャンセル

  • otn

    2017/08/01 13:01

    めんどくさいだけで、難しさはないと思いますが、何が出来ないのでしょうか?

    キャンセル

  • Lhankor_Mhy

    2017/08/01 14:11

    javascriptで取り扱える数値は2^53+1までなので、京以上の単位は表現できないと思います。

    キャンセル

回答 5

+3

この手のありがちなものは、WEB検索すればすぐ見つかります。

JavaScript 漢数字変換 - Google 検索

上記の2番目の

アラビア数字→漢数字変換(桁付き)する JavaScript - drk7jp

だと無量大数まで対応してます。

追記

ごめんなさい。

"正規表現を使わず"

という条件を見落としてました。
上記のリンク先は正規表現を使ってますね。

この条件を付けたのは、自分の勉強のためにということでしょうか。
ならば、もう少し自分で考えてみて、コードを書いて、
行き詰ったところ、想定通りにならないところをピンポイントで質問したほうが
スキルアップにつながるでしょう。

追記2

提示のコードはいいところまでいっています。
もっと効率的なコードもありますが、自分の学習のためということなので、提示のコードをなるべく活かしてアドバイスします。
まず、一気に一つの関数で無量大数までやろうとせずに、まずは4桁までの数値に千百十の桁を付加して変換する関数を作成するようにするといいでしょう。
提示のコードの一部を変更しました。テキストボックスに4桁以下の数を入力して、希望の結果になるのを確認してください。

function toKanji4(n) {
  var th = ["","千","二千","三千","四千","五千","六千","七千","八千","九千"];
  var  h = ["","百","二百","三百","四百","五百","六百","七百","八百","九百"];
  var  t = ["","十","二十","三十","四十","五十","六十","七十","八十","九十"];
  var  o = ["","一","二","三","四","五","六","七","八","九"];
  var s = '';
  var m = '';

  if (n == 0) {
    return '零';
  } else if (n < 0 || isNaN(n)) {
    return alert('漢数字に変換できません。');
  } else { 
    s = n.substr(-4);
    th = th [ Math.floor(s / 1000) ];
    h = h [ Math.floor(s / 100) % 10 ];
    t = t [ Math.floor(s / 10) % 10 ];
    o = o [ s % 10 ];
    m = th + h + t + o ;
    return m;
  }
}

function convert() {
  var n = document.getElementById('num').value;
  var result = document.getElementById('result');
  result.innerHTML = toKanji4(n);
}


ほとんど自分で書いたコードですのでやっていることの意味は理解できますよね。
うまく動作することが確認できたら、次は、
末尾から4桁ずつ取り出して、上記の関数で変換させて、それに万、億、兆の桁を付加してつなげていく関数を作成すればいいことになります。トライしてみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/01 14:01

    ご回答ありがとうございます。URLはすでに拝見したものでした、申し訳ございません。おっしゃる通り、勉強のため”正規表現を使わずに”という条件を課しております。

    >もう少し自分で考えてみて、コードを書いて、行き詰ったところ、
     想定通りにならないところをピンポイントで質問したほうがスキルアップにつながるでしょう。

    みなさんは一般的にどのくらい考えられるのでしょうか?私は二日間、1日12時間考えていたのですが、参考までに教えていただけますと幸いです。また、コードは書いてあるところまでですでに行き詰っておりまして…、仮説自体が立てられていないという状況で…。もう少し勉強しないと皆さまに申し訳ないですね。すみません。

    キャンセル

+2

とりあえず元の方ですが以下でエラーです substrを何に使おうとしているのかよくわかりませんが
s = n.substr(,);
s = n.substr(",");

また以下のようにしてしまうと
th = th [ Math.floor(s / 1000) ];

var th = ["","千","二千","三千","四千","五千","六千","七千","八千","九千"];
のデータを上書きしてしまうので別の変数に入れるようにした方がいいです

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/01 14:12

    substrでは、n.substr(~,4)という形にして、数字を4桁ずつ切り出して、変換していこうとしていました。上書きはしない方がいいんですね。別の変数に入れてみます。ありがとうございます。

    キャンセル

+2

全部は見ていませんが……
まずはこのへんが怪しそうです。

s = n.substr(,); //


追記:書いているうちに他の方の回答がついてかぶってしまいました。
このレベルの問題はデバッガでたやすく見つけ出せるはずなので、12時間一人で悩む前にまずは「ステップ実行」でしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/01 14:16

    申し訳ございません。数字を4桁ずつ切り出して変換していこうとしていたのですが、どうやっていいか分からず、そのままにしておりました。

    キャンセル

  • 2017/08/01 14:19

    でしたら、まずはそこを質問されたら良かったと思います。質問のフォーカスは絞ったほうがいいです。

    キャンセル

  • 2017/08/01 14:29

    質問をさらに絞ったほうが良かったんですね。はじめてだったとはいえ、もう少し他の方の投稿をちゃんと見て考えるべきでした。デバッガやステップ実行という言葉は知りませんでした。ありがとうございます!

    キャンセル

+2

なるべく短く書こうとしてみましたが……
4ケタに分割してロケールストリングに変換して配列にし、それぞれの要素に千百十をいれ、要素の間に兆億万の単位を入れる感じです。

n = 1000000001203450;

[...(
  function* (n){
    while ( n >= 1 ){
      const remainder = n % 10000;
      n = parseInt( n / 10000 );
      yield remainder;
    }
  }
)(n)].map(
  n => n.toLocaleString( 'ja-JP-u-nu-hanidec', {useGrouping: false} ).split('').reverse().map(
    (d, i)=> {
      if ( d == '〇' ) return '';
      if ( d == '一' ) return '一十百千'[i];
      return d + ' 十百千'[i];
    }
  ).reverse().join('') 
).map(
  (d, i)=> {
    if ( d == '千' && i != 0 ) return d.replace( '千', '一千' ) + " 万億兆"[i];
    if ( d == '' ) return '';
    return d + " 万億兆"[i];
  }
).reverse().join('').split(' ').join('');

/*
一千兆百二十万三千四百五十
*/

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/01 16:41

    ルール2を満たしていなかったので修正しました。

    キャンセル

0

皆様の回答とても勉強になります。
別の言語ですが私も最近、半角英数字を漢数字に
変換するプログラムを作っていました。

私のやり方は
1.数字を1文字ずつ分解して、その数字の位(10^n)を交互に入れたリストを作る。
2.そのリストをキーに予め用意しておいた辞書から漢数字を持ってくる。
3.最後に例外的な変更を行う。
というものでした。

正確に動くかどうかは分かりません。

using System;
using System.Collections.Generic;
using System.Linq;

namespace Kansuji
{
    class Program
    {
        static String Trans(string key)
        {
            key = key.Replace("+0", "");

            if(new string[]{ "^5", "^9", "^13" }.Contains(key))
            {
                key = "^1";
            }
            else if(new string[]{ "^6", "^10", "^14" }.Contains(key))
            {
                key = "^2";
            }
            else if(new string[]{ "^7", "^11", "^15" }.Contains(key))
            {
                key = "^3";
            }

            Dictionary<string, string> trans = new Dictionary<string, string>(){
                        {"1", "一"},
                        {"2", "二"},
                        {"3", "三"},
                        {"4", "四"},
                        {"5", "五"},
                        {"6", "六"},
                        {"7", "七"},
                        {"8", "八"},
                        {"9", "九"},
                        {"^1", "十"},
                        {"^2", "百"},
                        {"^3", "千"},
                        {"^4", "万"},
                        {"^8", "億"},
                        {"^12", "兆"},
            };

            return trans.ContainsKey(key) ? trans[key] : "";
        }

        static void Main()
        {
          string input = Console.ReadLine();

          List<string> keys = new List<string>();

          bool zero = true;

          for(int i = 0; i < input.Length; i ++)
          {
              if(input[i] != '0')
              {
                  keys.Add(input[i].ToString());

                  if(i != input.Length - 1)
                  {
                      keys.Add("^" + (input.Length - 1 - i).ToString());
                  }

                  zero = false;
              }
              else
              {
                  if(new int[] {4, 8, 12}.Contains(input.Length - 1 - i))
                  {
                      if(!"^8^12".Contains(keys.Last()))
                      {
                          if(keys.Last().Contains("+0")) continue;
                          keys.Add("^" + (input.Length - 1 - i).ToString() + "+0");
                      }
                  }
              }
          }

          if(zero)
          {
              Console.WriteLine("〇");
              return;
          }

          Console.WriteLine(string.Join(", ", keys));

          string[] result = keys.Select(e => Trans(e)).ToArray();

          string[] _ans = string.Join("", result)
                              .Replace("一十", "十")
                              .Replace("一百", "百")
                              .Replace("一千", "千")
                              .ToCharArray()
                              .Select(c => c.ToString())
                              .ToArray();

          for(int i = 0; i < _ans.Length; i ++)
          {
              if(input.Length < 5) continue;

              if(i == 0 || "兆億".Contains(_ans[i - 1]))
              {
                  if(i == _ans.Length - 1 || "兆億万".Contains(_ans[i + 1]))
                  {
                      if(_ans[i] == "千") _ans[i] = "一千";
                  }
              }
          }

          string ans = string.Join("", _ans);

          Console.WriteLine(ans);
        }
    }
}

 追記

using System;
using System.Collections.Generic;
using System.Linq;

namespace Kansuji
{
    class Program
    {
        static string Trans(string input)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>(){
                {"0", "〇"},
                {"1", "一"},
                {"2", "二"},
                {"3", "三"},
                {"4", "四"},
                {"5", "五"},
                {"6", "六"},
                {"7", "七"},
                {"8", "八"},
                {"9", "九"},
            };

            return dic[input];
        }

        static List<string[]> Slice(string[] input)
        {
            input = input.Reverse().ToArray();

            List<string[]> result = new List<string[]>();

            int count = 0;

            while(count + 4 <= input.Length)
            {
                string[] _t = new string[4];
                Array.Copy(input, count, _t, 0, 4);
                result.Add(_t);
                count += 4;
            }

            int rest = input.Length - count;

            if(rest != 0)
            {
                string[] _r = new string[4];

                for(int i = 0; i < 4 - rest; i++)
                {
                    _r[3 - i] = "0";
                }

                Array.Copy(input, count, _r, 0, rest);
                result.Add(_r);
            }


            for(int i = 0; i < result.Count; i++)
            {
                result[i] = result[i].Reverse().Select(e => Trans(e)).ToArray();
            }

            result.Reverse();

            return result;
        }

        static void Main(string[] args)
        {
            string input = args[0];

            if(int.Parse(input) == 0)
            {
                Console.WriteLine("〇");
                return;
            }

            List<string[]> _list = Slice(input.ToCharArray().Select(e => e.ToString()).ToArray());

            for(int i = 0; i < _list.Count; i++)
            {
                string[] _c = _list[i];

                for(int j = 0; j < _c.Length; j++)
                {
                    string _d = _c[j];

                    if(_d == "〇")
                    {
                        _d = "";
                    }
                    else if(_d == "一")
                    {
                        _d = "千百十一"[j].ToString();
                    }
                    else
                    {
                        _d = j < 3 ? _d + "千百十"[j].ToString() : _d;
                    }

                    _c[j] = _d;
                }

                _list[i] = _c;
            }

            string[] _k = new string[]{ "", "万", "億", "兆" };

            List<string> result = new List<string>();

            _list.Reverse();

            for(int i = 0; i < _list.Count; i++)
            {
                string[] arr = _list[i];

                bool next_flag = true;

                foreach(string s in arr)
                {
                    if(s != "") next_flag = false;
                }

                if(next_flag) continue;

                result.Add(_k[i]);

                string[] check = arr.Where(e => e != "").ToArray();

                result.Add(check.Length == 1 && check[0] == "千" && i != 0 ? "一千" : string.Join("", arr));
            }

            result.Reverse();

            Console.WriteLine(string.Join("", result));
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る