用分数表示循环小数(C#版)
文章目錄
- 前言
- 一、問題
- 二、分析
- 三、實現
- 1、界面設計
- 2、循環小數類設計
- 3、調用
- 4、運行結果
- 5、神奇的發現
- 總結
- 附錄
前言
????????最近學習C#,遇到這樣的一個問題:用分數表示循環小數 0.33(3)=1/3???0.285714(285714)=2/7 ,解決之后來記錄一下解決方案。
一、問題
????????用分數表示循環小數 0.33(3)=1/3???0.285714(285714)=2/7
二、分析
????????循環小數分純循環小數和混循環小數。
????????純循環小數的化法:先獲取循環體的值x,然后獲取循環體的位數n,然后將循環體的值x比上n個9,最后化簡。如,0.81(81),從這個數中我們可以獲取循環體的值為81,循環體的位數為2也就是到時候比上99,所以得出0.81(81)=(81/99)=9/11。
????????混循環小數的化法:先將其分解成為有限小數與純循環小數/10^k的和(這里的k是指循環體前面的小數位數),然后分別求出它們的分數形式,最后通分化簡。舉例如下:0.13(3),這里分解出來的有限小數為0.1、純循環小數為0.3(3)、k為1(因為循環體3前面的小數只有1位),所以得出0.13(3)=0.1+0.3(3)/10=2/15。
????????注意點:如果像前面0.33(3)這樣的數,它本來是純循環小數,但是由于它不是寫成0.3(3)這樣的形式,如果把它歸為純循環小數來書寫代碼將會提高代碼的復雜程度,所以我們把它歸類于混循環小數來處理。
三、實現
1、界面設計
????????1、輸入框:使用TextBox控件,并給它命名為cirNumTBox
????????2、顯示框:使用TextBox控件,給它命名為fracTBox,并將ReadOnly屬性設置成true
????????3、轉換按鈕:使用Button控件,并給它命名為changeBtn
2、循環小數類設計
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace CycNumExpress {/// <summary>/// 此類用來描述無限循環小數,擁有循環小數和分數兩個屬性/// </summary>public class CircleNum{string circNum; //循環小數public string CircNum{get { return circNum; }set { circNum = value; }}string fraction; //循環小數的分數表示public string Fraction{get { return fraction; }set { circNum = value; }}public CircleNum(){}public CircleNum(string circNum){this.circNum = circNum;fraction = ChangeToFraction();}/// <summary>/// 此方法用來將無限循環小數轉換成分數表示/// </summary>/// <returns>無限循環小數的分數表示</returns>public string ChangeToFraction(){string circBody; //循環體string acycBody; //非循環體int num; //記錄循環體前面小數點的位數string fraction;//分數circBody = GetCircBody(circNum);//獲取循環體acycBody = GetAcycBody(circNum);//獲取非循環體//獲取循環體前的小數位數,如 1.13(3)其num的值為1num = GetBCirBodyDecimal(circNum);fraction = GetFraction(circBody, acycBody, num);//獲取分數表示return fraction;}/// <summary>/// 此函數用來獲取循環體,如1.13(3),則獲取值為3/// </summary>/// <param name="circNum">循環小數</param>/// <returns>循環體</returns>public string GetCircBody(String circNum){string circBody = "0";int firstIndex = circNum.IndexOf("(") + 1; //讀的首位置下標int lastIndex = circNum.LastIndexOf(")") - 1;//讀取的尾下標int readNum = lastIndex - firstIndex + 1;//讀取的數目if ((firstIndex > 0) && readNum > 0){circBody = circNum.Substring(firstIndex, readNum);//截取循環體}return circBody;}/// <summary>/// 此函數用來獲取非循環體,如1.13(3),則獲取值為1.1/// </summary>/// <param name="circNum">循環小數</param>/// <returns>非循環體</returns>public string GetAcycBody(String circNum){string acycBody = "";int firstIndex = 0; //讀的首位置下標int lastIndex = circNum.LastIndexOf(GetCircBody(circNum) + "(") - 1;//讀取的尾下標int readNum = lastIndex - firstIndex + 1;//讀取的數目if (firstIndex != -1 && readNum > 0){acycBody = circNum.Substring(firstIndex, readNum);//截取循環體if (acycBody.EndsWith("."))//如果小數點后沒有數了,那么就截去小數點{acycBody = circNum.Substring(firstIndex, acycBody.Length - 1);//截取循環體}}else{acycBody = circNum;}return acycBody;}/// <summary>/// 此函數用來獲取循環體前的小數位數,如 1.13(3)其num的值為1/// </summary>/// <param name="circNum">循環小數</param>/// <returns>循環體前的小數位數</returns>public int GetBCirBodyDecimal(String circNum){int num = 0;string acycBody = GetAcycBody(circNum);int firstIndex = acycBody.IndexOf(".") + 1; //讀的首位置下標int lastIndex = acycBody.Length - 1;//讀取的尾下標int readNum = lastIndex - firstIndex + 1;//讀取的數目if ((firstIndex > 0) && (readNum > 0)){num = acycBody.Substring(firstIndex, readNum).Length;//截取循環體}return num;}/// <summary>/// 此函數用來獲取循環小數的分數表示/// </summary>/// <param name="circBody">循環體</param>/// <param name="acycBody">非循環體</param>/// <param name="num">循環體前的小數位</param>/// <returns>循環小數的分數表示</returns>public string GetFraction(string circBody, string acycBody, int num){string fraction;long mol; //分子long deno = 0; //分母string op = "";if (int.Parse(circBody) == 0){deno = 1;}else{for (int i = 1; i <= circBody.Length; ++i)deno = deno * 10 + 9;}deno = deno * (int)Math.Pow(10, num);//為分母賦值mol = long.Parse(circBody) + (long)(Math.Abs(decimal.Parse(acycBody) * deno));//為分子賦值if (acycBody.Substring(0, 1) == "-")//記錄循環小數的符號{op = "-";}long gcd = FindGCD(mol, deno);//尋找最大公約數fraction = op + (mol / gcd).ToString() + ((deno / gcd == 1) ? "" : "/" + (deno / gcd).ToString());//得到最簡分數return fraction;}/// <summary>/// 本函數用輾轉相除法來求解最大公約數/// </summary>/// <param name="num1">整數1</param>/// <param name="num2">整數2</param>/// <returns>最大公約數</returns>public long FindGCD(long num1, long num2){long temp;num1 = Math.Abs(num1);num2 = Math.Abs(num2);temp = num1 % num2;while (temp != 0){num1 = num2;num2 = temp;temp = num1 % num2;}return num2;}} }3、調用
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace CycNumExpress {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void change(object sender, EventArgs e){//有參構造實現//CircleNum circNum = new CircleNum(cirNumTBox.Text);//fracTBox.Text = circNum.Fraction;//無參構造實現CircleNum circNum = new CircleNum();circNum.CircNum = cirNumTBox.Text;fracTBox.Text = circNum.ChangeToFraction();}} }4、運行結果
純循環小數轉換
混循環小數轉換
整數轉換
有限小數轉換
5、神奇的發現
????????在不斷測試的過程中,遇到了一個神奇的事情,在循環小數中,如果帶有9的循環體,那么就會得到近似解,比如0.9(9)=1。剛剛發現被驚到了,還以為遇到什么神奇的bug,后來仔細一想這個結果是正確的,詳細證明過程如下:
證明1:
????????設0.9(9)=x。
????????那么:10x=9.9(9)則9x=10x-x=9.9(9)-0.9(9)=9。
????????所以x=1,得證。
證明2:
????????設0.9 (9)為無限遞縮等比數列。
????????那么:0.9(9)=0.9+0.09+0.009+…+0.90.1的(n-1)次方=
????????????????????0.9(1-0.1的n次方)/(1-0.1)=1-0.1的n次方。
????????所以當n趨向于無窮大時0.1的n次方趨向于0 所以0.9(9)=1。
總結
????????將循環小數轉換成其分數形式看起來復雜,但是經過分析,將問題分解細化,還是可以找到比較好的解決方案的,希望此篇文章可以幫助到你。
附錄
源碼下載:https://github.com/luotingyang/MyRepository/tree/C%23
總結
以上是生活随笔為你收集整理的用分数表示循环小数(C#版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA-获取无限循环小数的循环节
- 下一篇: angular的生命周期