从第一种思路的实现推导出第二种思路实现,从第二种思路推导出终极算法,再从终极算法归纳总结优化第一种思路,从下面发布的代码可以看到演化轨迹.MSDN查询
string 标准人民币金额制式模板 = "零仟·零佰·零拾·零☆不可说☆·零仟·零佰·零拾·零☆无量·零仟·零佰·零拾·零不可思议·零仟·零佰·零拾·零那由他·零仟·零佰·零拾·零阿僧祇·零仟·零佰·零拾·零恒河沙·零仟·零佰·零拾·零极·零仟·零佰·零拾·零载·零仟·零佰·零拾·零正·零仟·零佰·零拾·零涧·零仟·零佰·零拾·零沟·零仟·零佰·零拾·零穰·零仟·零佰·零拾·零秭·零仟·零佰·零拾·零垓·零仟·零佰·零拾·零京·零仟·零佰·零拾·零兆·零仟·零佰·零拾·零亿·零仟·零佰·零拾·零万·零仟·零佰·零拾·零元"
, 中文值 = "零壹贰叁肆伍陆柒捌玖", 转换输出标准 = "", 缩读处理 = "零仟零佰零拾";
string[] 反转单位集合 = 标准人民币金额制式模板.Split('·').Reverse().ToArray();
long 要转换的数字 = new Random().Next(int.MaxValue);
int 位数 = 0, 读单位 = 0;
Console.WriteLine("要转换的数字:" + 要转换的数字.ToString() + "转换:");
do
{
转换输出标准 = 转换输出标准.Insert(0, 反转单位集合[位数].Replace("零", 中文值[(int)(要转换的数字 % 10)].ToString()));
++位数;
} while ((要转换的数字 /= 10) > 0);
Console.WriteLine(转换输出标准);
/*会计标准的输出就是上面这样了,来看看如何生成读的文字,首先说明,代码修改和优化在写完后期进行,这是个人习惯了.
其实规则还是很单纯的,首先处理最多4项,再处理左右321项,从最多处理开始,左补零,右单位,最后处理单项进阶单位*/
do
{
string 零单位 = 反转单位集合[读单位]; string[] 四位数 = { "" };
if (位数 > 读单位 + 4)
{
string 进位 = 反转单位集合[读单位 + 4].Replace("零", "");
四位数 = 转换输出标准.Split(进位.ToCharArray());
四位数[0] += 进位;
转换输出标准 = 四位数[四位数.Length - 1];
}
转换输出标准 = 转换输出标准.Replace(缩读处理 + 零单位, "");/*4*/
转换输出标准 = 转换输出标准.Replace(缩读处理.Substring(2) + 零单位, 零单位).Replace(缩读处理, "零");/*3*/
转换输出标准 = 转换输出标准.Replace(缩读处理.Substring(4) + 零单位, 零单位).Replace(缩读处理.Remove(4), "零").Replace(缩读处理.Substring(2), "零");/*2*/
转换输出标准 = 转换输出标准.Replace(缩读处理.Substring(4), "零").Replace(缩读处理.Remove(2), "零").Replace(缩读处理.Substring(2, 2), "零").Replace(零单位, 零单位.Replace("零", ""));/*1*/
if (四位数[0] != "") 转换输出标准 = 四位数[0] + 转换输出标准;
读单位 += 4;
} while (位数 > 读单位);/*完美实现第一种思路 1000004000300102;//*/
Console.WriteLine(转换输出标准 + (转换输出标准.Contains("元") ? "" : "元"));
要转换的数字 = new Random().Next(int.MaxValue);
转换输出标准 = ""; 位数 = 0;/*用到上面用过的变量时的初始化*/
bool 零补 = false, 是否加 = false;
Console.WriteLine("要转换的数字:" + 要转换的数字.ToString() + "转换:");
Func<long, bool> 四位判断 = delegate(long 信息)
{
long 代数 = 信息, 计位 = 0;
bool 逻辑 = false;
do
{
if (代数 % 10 > 0)
逻辑 = true ;
代数 /= 10;
} while (++计位 < 4);
return 逻辑;
};
do
{
读单位 = (int)(要转换的数字 % 10);
if (位数 % 4 == 0)
是否加 = 四位判断(要转换的数字);
if (读单位 > 0)
{
转换输出标准 = 转换输出标准.Insert(0, 反转单位集合[位数].Replace("零", 中文值[读单位].ToString()));
零补 = true ;
}
else
if (是否加)
{
if (位数 % 4 == 0)
转换输出标准 = 转换输出标准.Insert(0, 反转单位集合[位数].Replace("零", ""));
else
if (零补)
转换输出标准 = 转换输出标准.Insert(0, "零");
零补 = false;
}
++位数;
} while ((要转换的数字 /= 10) > 0);/*完美实现第二种思路*/
Console.WriteLine(转换输出标准 + (转换输出标准.Contains("元") ? "" : "元"));
/*最后,为什么要写字符串模板?因为,处理代码可以写为一个函数,传递字符串模板给函数去处理即可,无位数限制,可扩展。*/
要转换的数字 = new Random().Next(int.MaxValue);
Console.WriteLine(要转换的数字.ToString() + " 终极算法:");
转换输出标准 = ""; 位数 = 0;/*用到上面用过的变量时的初始化*/
bool 选加 = true, 是否 = false; string 选单位 = "";
Action 插入 = delegate()
{
if (是否)
{
转换输出标准 = (选加 ? 选单位 : "零") + 转换输出标准;
是否 = false;
}
};
do/*数字转中文金额终极算法,可申请算法专利了,哈哈......*/
{
读单位 = (int)(要转换的数字 % 10);
if (位数 % 4 == 0)
{
if (是否 && !选加) 插入();/*第三位0的处理,单位未加前不加零.*/
选单位 = 反转单位集合[位数].Replace("零", "");
选加 = true; 是否 = false;/*逻辑还原初始化.*/
}
if (读单位 > 0)
{
插入();
转换输出标准 = 反转单位集合[位数].Replace("零", 中文值[读单位].ToString()) + 转换输出标准;
选加 = false;
}
else
是否 = true;
++位数;
} while ((要转换的数字 /= 10) > 0);/*完美实现第三种思路*/
Console.WriteLine(转换输出标准 + (转换输出标准.Contains("元") ? "" : "元"));
string[] 小数中文集 = { "角", "分", "厘", "毫", "丝", "忽", "微", "纤", "沙", "尘", "埃", "渺", "莫", "模糊", "逡巡", "须臾", "瞬息", "弹指", "刹那", "六德", "空虚", "☆清静" };
double 要转换的小数 = new Random().Next(int.MaxValue) *.0000000001; //.1020030004;
string 小数字符串 = 要转换的小数.ToString(), 小数输出标准 = "";
int 取位 = 0, 总位 = 小数字符串.Length, 读数值 = 0;
bool 加入 = false;
do
{
读数值 = int.Parse(小数字符串[取位 + 2].ToString());/*变为0.1020030004为此+2*/
if (读数值 > 0)
{
if (加入) 小数输出标准 += "零";
小数输出标准 += 中文值[读数值].ToString() + 小数中文集[取位];
加入 = false;
}
else
加入 = true;
} while (++取位 + 2 < 总位);
Console.WriteLine(小数字符串 + " 小数转换输出标准:\n" + 小数输出标准);
后期代码维护与优化:
Action<string> 整理 = delegate(string 单位)
{
转换输出标准 = 转换输出标准
.Replace(缩读处理 + 单位, "")
.Replace(缩读处理.Substring(2) + 单位, 单位)
.Replace(缩读处理, "零")
.Replace(缩读处理.Substring(4) + 单位, 单位)
.Replace(缩读处理.Remove(4), "零")
.Replace(缩读处理.Substring(2), "零")
.Replace(缩读处理.Substring(4), "零")
.Replace(缩读处理.Remove(2), "零")
.Replace(缩读处理.Substring(2, 2), "零")
.Replace(单位, 单位.Replace("零", ""));
};
do
{
转换输出标准 = 反转单位集合[位数].Replace("零", 中文值[(int)(要转换的数字 % 10)].ToString()) + 转换输出标准;
if (位数 > 0 && 位数 % 4 == 0) 整理(反转单位集合[位数 - 4]);
++位数;
} while ((要转换的数字 /= 10) > 0);/*完美实现第一种思路,后期代码维护与优化*/
整理(反转单位集合[位数 - (位数 % 4 > 0 ? 位数 % 4 : 4)]);
int 自增检验数 = 0;
var 零单位 = 反转单位集合.Distinct().Reverse();
var 相邻单位 = 零单位.Take(零单位.Count() - 2).Select((单位, 序) => 单位.Replace("零", "") + 零单位.Skip(1).Select(相邻 => 相邻.Replace("零", "")).ToArray()[序]);
var 验证集合 = 零单位.Concat(相邻单位).Concat(new string[] { "零零" });/*答复来自论坛提问:固定数组变长,用连接两个数组函数Concat和创建数组函数ToArray完成*/零单位 = 零单位.Concat(相邻单位).Concat(new string[] { "零零" }).ToArray();
do
{
要转换的数字 = ++自增检验数;
do
{
转换输出标准 = 反转单位集合[位数].Replace("零", 中文值[(int)(要转换的数字 % 10)].ToString()) + 转换输出标准;
if (位数 > 0 && 位数 % 4 == 0) 整理(反转单位集合[位数 - 4]);
++位数;
} while ((要转换的数字 /= 10) > 0);/*完美实现第一种思路,后期代码维护与优化*/
整理(反转单位集合[位数 - (位数 % 4 > 0 ? 位数 % 4 : 4)]);
Console.WriteLine(转换输出标准 + (转换输出标准.Contains("元") ? "" : "元"));
/*校验正确性:1.零单位 2.相邻单位 3.连零*/
foreach (string 元素 in 验证集合)
if (转换输出标准.Contains(元素))
{
Console.Beep();
Console.WriteLine(元素);
return;
}
转换输出标准 = ""; 位数 = 0;
} while (自增检验数 < int.MaxValue);
/*之上代码逻辑经得起推敲.*/
// if (要转换的数字 % 10 == 0) 零补 = true;
// 要转换的数字 /= 10;
// if (零补 && 要转换的数字 % 10 > 0)/*完成任意个0的处理*/
// 零补 = false;