您的位置:首页 > 其它

字符串四则运算之一无限位数相加的设计

2015-11-01 07:29 351 查看
        static string 无限位数相加(string 数字1, string 数字2)
{
string 和 = "";
if (数字1.Length < 数字2.Length) { 和 = 数字1; 数字1 = 数字2; 数字2 = 和; 和 = ""; }
int 位1 = 数字1.Length - 1, 位2 = 数字2.Length - 1;
int 进位值 = 0;
do
{
int 相加值 = int.Parse(数字1[位1].ToString()) + (位2 >= 0 ? int.Parse(数字2[位2].ToString()) : 0) + 进位值;/*写法适用于任意位的运算*/
进位值 = 相加值 > 9 ? 相加值 / 10 : 0;/*获取进位*/
和 = (相加值 % 10).ToString() + 和;/*合成*/
--位2;
} while (--位1 >= 0);
if (进位值 > 0) 和 = 进位值.ToString() + 和;/*最后合成*/

return 和;
}
static void Main(string[] args)
{
从头: DateTime 测试开始时间 = DateTime.Now;

/*字符串里面是数值,且不受字数限制。49+51
如两个字符串相加“121343435”+“3453245”,设计的程序是:个位与个位相加,满10进1,十位于十位相加...
如果设计的乘法,也是个位先和个位相乘...完了错开一位相加 采取最原始的方法,就像小学学习四则运算一样,一步一步进行
不能把字符串先转换为int等类型在进行运行,因为int类型储存数值长度短,这个程序设计的意义就是可以进行不受字数限制的四则运算。
谢谢各位大神啦,希望可以多一些注释,尽可能详细。因为刚接触C#,这是课堂作业。超级感谢!!

首先设计加法运算:
* 规则:两个数的对应位相加,从最低的个位开始进行运算(从右到左),逢十进一,进位数与高一位两个数相加后的个位数相加;
* 取数:字符串本身就是数组,因此,可以直接用序直接取字符串内的任意位置字符,如“123456789”[8]获取字符串中的9字;
* 转换:这里只写整数运算int类型的算法;
* 构思:从两个字符串各自的最后一个字符开始取出,直到字符串的第一个字符结束;
* 写一个无限位数字相加的函数来处理,该函数返回运算后的结果,函数需要传递两个字符串数字参数;
* static string 无限位数字相加(string 数字1, string 数字2)
{
string 和 = "";

return 和;
}
* 接着写算式代码:
* int 位1 = 数字1.Length - 1, 位2 = 数字2.Length - 1;
* int 相加值 = int.Parse(数字1[位1].ToString()) + int.Parse(数字2[位2].ToString()) + 进位值;写法适用于任意位的运算
* 接着写进位的处理:
* int 进位值 = 相加值 > 9 ? 相加值 / 10 : 0;获取进位
* 接着写和输出处理:
* 和 = (相加值 % 10).ToString() + 和;合成
* 这样位的加法运算基本构思结束;
* 接着写循环各位数的处理:
* do
* {
* } while ();
* int 序 = 位1;
* while (--序 >= 0);设置条件
* 接着把处理语句放进循环体内:
* do
* {
* int 相加值 = int.Parse(数字1[序].ToString()) + int.Parse(数字2[序].ToString()) + 进位值;
* 进位值 = 相加值 > 9 ? 相加值 / 10 : 0;
* 和 = (相加值 % 10).ToString() + 和;
* } while (--序 >= 0);
* 第一次调试:string 数字1 = "49", 数字2 = "51";无限位数字相加(数字1, 数字2);观察结果是否按设计意图执行,验证程序正确性;
* 接着写位数读取限制的处理:之上程序在处理相同位数是可以的,当两个字符串长度不同时,应分别进行处理,避免取位错误和超出,修改如下:
* int 序2 = 位2;
* int 相加值 = int.Parse(数字1[序1].ToString()) + (序2 >= 0 ? int.Parse(数字2[序2].ToString()) : 0) + 进位值;
* --序2;
* } while (--序1 >= 0);
* 最后处理字符串长度最长的确保存在数字1中:
* if (数字1.Length < 数字2.Length) { 和 = 数字1; 数字1 = 数字2; 数字2 = 和; 和 = ""; }
* 由于对字符串进行长度存储位置的处理之后,可以对代码进行初步优化,最终代码如下:
* 可以发现该代码有值得优化的地方,就是超过数字2位数后可以不用循环运算,直接跳出循环,用截取去合成最终结果,可以提高运算速度。
*/

string 数字1 = "123654789632587415935749123654789632587415935749", 数字2 = "151";
无限位数相加(数字1, 数字2);

static string 无限位数相加(string 数字1, string 数字2)
{
string 和 = "";
if (数字1.Length < 数字2.Length) { 和 = 数字1; 数字1 = 数字2; 数字2 = 和; 和 = ""; }
int 位1 = 数字1.Length - 1, 位2 = 数字2.Length - 1;
int 进位值 = 0;
do
{
int 相加值 = int.Parse(数字1[位1].ToString()) + (位2 >= 0 ? int.Parse(数字2[位2--].ToString()) : 0) + 进位值;/*写法适用于任意位的运算*/
进位值 = 相加值 > 9 ? 相加值 / 10 : 0;/*获取进位*/
和 = (相加值 % 10).ToString() + 和;/*合成*/
if (位2 < 0 && 进位值 == 0) break;/*长度短的结束,且无进位*/
} while (--位1 >= 0);
if (进位值 > 0) 和 = 进位值.ToString() + 和;/*最后合成*/
if (位1 >= 0) 和 = 数字1.Substring(0, 位1) + 和;/*如果提前退出循环截取合成*/
return 和;
}
验证程序
int 数字1 = 1, 数字2 = 1;
do
{
do
{
string aa = (数字1 + 数字2).ToString();
string bb = 无限位数相加(数字1.ToString(), 数字2.ToString());
if (aa != bb)
{
Console.WriteLine("发现错误:{0},{0}", aa, bb);
break;
}
else
{
Console.WriteLine("正确运算:{0},{0}", aa, bb);
System.Threading.Thread.Sleep(100);
}
} while (++数字2 < 1000000);
数字2 = 1;
} while (++数字1 < 1000000);

改为可接续运算:
static string[] 无限位数相加(string 被加数, string 加数, bool 续 = false, string 续进 = "0")
{
string[] 和 = { "", "0" };
bool 自适 = (被加数.Length < 加数.Length) ? false : (被加数.Length > 加数.Length) ? true : false;
int 位1 = 被加数.Length - 1, 位2 = 加数.Length - 1, 进位值 = int.Parse(续进);
do
{
int 相加值 = (位1 >= 0 ? int.Parse(被加数[位1--].ToString()) : 0) + (位2 >= 0 ? int.Parse(加数[位2--].ToString()) : 0) + 进位值;/*写法适用于任意位的运算*/
进位值 = 相加值 > 9 ? 相加值 / 10 : 0;/*获取进位*/
和[1] = 进位值.ToString();
和[0] = (相加值 % 10).ToString() + 和[0];/*合成*/
if ((自适 ? 位2 : 位1) < 0 && 进位值 == 0)/*长度短的结束,且无进位*/
{
续 = false;
break;
}
} while ((自适 ? 位1 : 位2) >= 0);
if (进位值 > 0 && !续)/*最后合成*/
和[0] = 进位值.ToString() + 和[0];
if ((自适 ? 位1 : 位2) >= 0)
和[0] = (自适 ? 被加数 : 加数).Substring(0, (自适 ? 位1 : 位2) + 1) + 和[0];/*如果提前退出循环截取合成*/
return 和;
}
这里示例:把一段数字字符串分段进行运算的结果是一样的,这样就可以把要计算的数字字符串分别保存在连续的文本文件中读入进行运算,是真正的无限位数运算,每个文本文件最大可以保存int.MaxValue位字符,无论N个文本文件都可以进行读入传送运算了,这里规定:字符串为尾对齐进行运算,因此,存在文件中的字符串也应该是从文件序号1为数字头开始存储的,但要注意最后一个文件必须是位数对齐的,最前一个文件可以是任意不等字符串的,比如:有2个要运算的字符串数字分别保存在4个文本文件中,其中一个字符串分段保存在名为"被加数1"和"被加数2"中,另一个字符串被保存在"加数1"和"加数2"中,假设这2个字符串长度差4个字符,应该把"被加数2"和"加数2"存储同样数量的字符数,最后把不同数量的剩余字符串各自保存在序号1中.
string[,] aa = { { "494949494949494949494949", "515151515151515151515151" }, { "494949494949494949494949", "515151515151515151515151" }, { "494949494949494949494949", "515151515151515151515151" }, { "494949494949494949494949", "515151515151515151515151" } };
int 序 = aa.Length / 2 - 1; string bb = ""; string[] cc = { "", "0" };
do
{
cc = 无限位数相加(aa[序, 0], aa[序, 1], (序 > 0 ? true : false), cc[1]);
bb = cc[0] + bb;
} while (--序 >= 0);
Console.WriteLine("正确运算:{0}", bb);
Console.WriteLine("正确运算:{0}", 无限位数相加("494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949", "515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151"));

以上代码未经细致优化,如数据格式转换的优化等
问题来源:以及1到10的阶乘和c#BigIntger类
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: