循環小数生成

循環小数生成


資料:

ver0.8


<アルゴリズム解説>
10進桁あがりの割算を繰り返し、割算と余りの履歴を記憶して、同一の履歴を計算時に確認
過去に同一の計算履歴が存在すれば、そこで循環節の"節"を発見として計算を終了し集計する
また、割算の計算結果が商0余り0の場合は「割り切れた」として、これも計算終了して集計する

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Test1 : MonoBehaviour
{
      void Start ()
       {
               DispLoopNumber (3);
               DispLoopNumber (6);
               DispLoopNumber (13);
               DispLoopNumber (43);
               DispLoopNumber (998);
       }

      void DispLoopNumber (int denominator)
       {
               LoopNumber lp = new LoopNumber (denominator);
               print (string.Format ("1/{0} : 循環開始位置=小数点{1}桁目:循環部の長さ={2}", lp.Denominator, lp.StartLoop, lp.Digits));
               print ("計算結果:" + lp.Number);
               print ("循環部:" + lp.LoopNum);
       }

      //循環小数を生成
       class LoopNumber
       {
               int denominator;        //分数の分母部
               int digits;
               string number = "";
               bool noLoop = false;

              List<Num> numList = new List<Num> ();
               
               //ctor
               public LoopNumber (int denominator)
               {
                       this.denominator = denominator;
                       int numerator = 10;        //分子
                       int div, remaind;

                      do {
                               div = numerator / denominator;
                               remaind = numerator % denominator;
                               number += div;
                               //初回時は初期化されていないのでマイナスの値になる
                               digits = numList.FindIndex (x => x.div == div && x.remaind == remaind);
                               numList.Add (new Num (){div=div,remaind=remaind});
                               if (digits >= 0) {
                                       break;
                               }    
                               numerator = remaind * 10;
                       } while (remaind!=0);

                      if (numerator == 0) {
                               noLoop = true;
                       }
               }

              //計算した値
               public string Number {
                       get{ return "0." + number;}
               }

              //循環部分のみ取り出した文字列
               public string LoopNum {
                       get{ return noLoop ? "割り切れたので循環小数ではありません" : number.Substring (digits, number.Length - digits - 1);}
               }

              //循環開始桁
               public int StartLoop {
                       get{ return digits + 1;}
               }

              //循環部分の数
               public int Digits {
                       get{ return noLoop ? 0 : numList.Count - digits - 1;}
               }

              //循環部分の数
               public int Denominator {
                       get{ return denominator;}
               }

              //割った答えと余りを保存して置き後で参照する
               struct Num
               {
                       internal int div;
                       internal int remaind;
               }
       }
}

プロトタイプ


number:循環小数のループ部
zero:ループ間に挿入するゼロの個数

using UnityEngine;
using System.Collections;

public class LoopGen : MonoBehaviour
{

      public int number;
       public int zero;

      void Start ()
       {
               print (LoopGenerate (number, zero));
       }

      double LoopGenerate (int number, int zero)
       {
               int digits = Mathf.CeilToInt (Mathf.Log10 (number)) + zero;
               double denominator = 1;
               for (int i = 0; i < digits; i++) {
                       denominator *= 10;
               }
               denominator --;
               return number / denominator;
       }
}

  • 最終更新:2014-08-09 17:46:01

このWIKIを編集するにはパスワード入力が必要です

認証パスワード