这个代码是2003年写的了.当时用的是vc6.已在pudn网站公开过了,
近来看到这样一个消息:微软的Visual Studio Internationalization Pack包含East Asia Numeric Formatting Library
已经有这样的转换功能,但我还没来得及细看.虽然这段代码很短,但是经过较多的测试,并且符合国家标准.我希望它可以挑战其他转换算法(我既希望我的算法是最好的,但是我更希望看到更好的算法).
public static string GetChineseNum(string strType, string strIn)
{ string m_1, m_2, m_3, m_4, m_5, m_6, m_7, m_8, m_9;
//m_1
m_1 = strIn;
string numNum = "0123456789.";
string numChina = "零壹贰叁肆伍陆柒捌玖点";
string numChinaWeigh = "个拾佰仟万拾佰仟亿拾佰仟万拾佰仟亿";
//m_1.Format("%.2f", atof(m_1));
m_1 = (float.Parse(strIn)).ToString("f2");
m_2 = m_1;
m_3 = m_4 = "";
//m_2:1234->壹贰叁肆
for (int i = 0; i < 11; i++)
{
//m_2=m_2.Replace(numNum.Mid(i, 1), numChina.Mid(i * 2, 2));
m_2 = m_2.Replace(numNum.Substring(i, 1), numChina.Substring(i, 1));
} //m_3:佰拾万仟佰拾个
int iLen = m_1.Length;
if (iLen > 16)
{
m_8 = m_9 = "越界错!";
return "";
}
if (m_1.IndexOf('.') > 0)
iLen = m_1.IndexOf('.'); for (int i = iLen; i >= 1; i--)
{
m_3 += numChinaWeigh.Substring(i - 1, 1);
}
//m_4:2行+3行 for (int i = 0; i < m_3.Length; i++)
{
m_4 += m_2.Substring(i, 1) + m_3.Substring(i, 1);
}
//m_5:4行去"0"后拾佰仟 m_5 = m_4;
m_5 = m_5.Replace("零拾", "零");
m_5 = m_5.Replace("零佰", "零");
m_5 = m_5.Replace("零仟", "零");
//m_6:00->0,000->0 m_6 = m_5;
for (int i = 0; i < iLen; i++)
m_6 = m_6.Replace("零零", "零"); //m_7:6行去亿,万,个位"0"
m_7 = m_6;
m_7 = m_7.Replace("亿零万零", "亿零");
m_7 = m_7.Replace("亿零万", "亿零");
m_7 = m_7.Replace("零亿", "亿");
m_7 = m_7.Replace("零万", "万");
if (m_7.Length > 2)
m_7 = m_7.Replace("零个", "个"); //m_8:7行+2行小数->数目
m_8 = m_7;
m_8 = m_8.Replace("个", "");
if (m_2.Substring(m_2.Length - 3, 3) != "点零零")
m_8 += m_2.Substring(m_2.Length - 3, 3); //m_9:7行+2行小数->价格
m_9 = m_7;
m_9 = m_9.Replace("个", "圆");
if (m_2.Substring(m_2.Length - 3, 3) != "点零零")
{
m_9 += m_2.Substring(m_2.Length - 2, 2);
m_9 = m_9.Insert(m_9.Length - 1, "角");
m_9 += "分";
}
else m_9 += "整";
if (m_9 != "零圆整")
m_9 = m_9.Replace("零圆", "");
m_9 = m_9.Replace("零分", "整");
if (strType == "数量")
return m_8;
else
return m_9; }
近来看到这样一个消息:微软的Visual Studio Internationalization Pack包含East Asia Numeric Formatting Library
已经有这样的转换功能,但我还没来得及细看.虽然这段代码很短,但是经过较多的测试,并且符合国家标准.我希望它可以挑战其他转换算法(我既希望我的算法是最好的,但是我更希望看到更好的算法).
public static string GetChineseNum(string strType, string strIn)
{ string m_1, m_2, m_3, m_4, m_5, m_6, m_7, m_8, m_9;
//m_1
m_1 = strIn;
string numNum = "0123456789.";
string numChina = "零壹贰叁肆伍陆柒捌玖点";
string numChinaWeigh = "个拾佰仟万拾佰仟亿拾佰仟万拾佰仟亿";
//m_1.Format("%.2f", atof(m_1));
m_1 = (float.Parse(strIn)).ToString("f2");
m_2 = m_1;
m_3 = m_4 = "";
//m_2:1234->壹贰叁肆
for (int i = 0; i < 11; i++)
{
//m_2=m_2.Replace(numNum.Mid(i, 1), numChina.Mid(i * 2, 2));
m_2 = m_2.Replace(numNum.Substring(i, 1), numChina.Substring(i, 1));
} //m_3:佰拾万仟佰拾个
int iLen = m_1.Length;
if (iLen > 16)
{
m_8 = m_9 = "越界错!";
return "";
}
if (m_1.IndexOf('.') > 0)
iLen = m_1.IndexOf('.'); for (int i = iLen; i >= 1; i--)
{
m_3 += numChinaWeigh.Substring(i - 1, 1);
}
//m_4:2行+3行 for (int i = 0; i < m_3.Length; i++)
{
m_4 += m_2.Substring(i, 1) + m_3.Substring(i, 1);
}
//m_5:4行去"0"后拾佰仟 m_5 = m_4;
m_5 = m_5.Replace("零拾", "零");
m_5 = m_5.Replace("零佰", "零");
m_5 = m_5.Replace("零仟", "零");
//m_6:00->0,000->0 m_6 = m_5;
for (int i = 0; i < iLen; i++)
m_6 = m_6.Replace("零零", "零"); //m_7:6行去亿,万,个位"0"
m_7 = m_6;
m_7 = m_7.Replace("亿零万零", "亿零");
m_7 = m_7.Replace("亿零万", "亿零");
m_7 = m_7.Replace("零亿", "亿");
m_7 = m_7.Replace("零万", "万");
if (m_7.Length > 2)
m_7 = m_7.Replace("零个", "个"); //m_8:7行+2行小数->数目
m_8 = m_7;
m_8 = m_8.Replace("个", "");
if (m_2.Substring(m_2.Length - 3, 3) != "点零零")
m_8 += m_2.Substring(m_2.Length - 3, 3); //m_9:7行+2行小数->价格
m_9 = m_7;
m_9 = m_9.Replace("个", "圆");
if (m_2.Substring(m_2.Length - 3, 3) != "点零零")
{
m_9 += m_2.Substring(m_2.Length - 2, 2);
m_9 = m_9.Insert(m_9.Length - 1, "角");
m_9 += "分";
}
else m_9 += "整";
if (m_9 != "零圆整")
m_9 = m_9.Replace("零圆", "");
m_9 = m_9.Replace("零分", "整");
if (strType == "数量")
return m_8;
else
return m_9; }
解决方案 »
- C#不可以有脱离命名空间和类的公有函数调用,那么我们可以将自己暂时无法归类的经常用到的自编函数安排在一个静态类中使用怎么样,因为静态类中的函数可以直接调用吗。这是否等同于VB、C++等直接调用了公有函数。
- 用什么控件可以将在内存中复制的图片按一下按钮放在该控件内及编程思路
- C#
- 请问如何写一个像ToolBar一样的集合类控件
- 窗口中如何显示CAD图形
- 设置客户端按钮的样式表问题?
- 请问大家做Blog有没有什么好的软件介绍,主要做blog的前台!要好用的软件!
- C#的.Remove方法我这些的有问题?为什么StartIndex 不能小于 0
- 如何实现 压缩一张图片(JPG)(不改变尺寸,只改变质量)到一个固定的字节数比如120,000 byte
- 两个问题rationalXDE和c#中的异常处理
- .net 的消息处理问题
- 2003的项目转VS2008
string sPrice = SomeStaticClass.GetChineseNum("价格","123.45");//得到价格
string sCount = SomeStaticClass.GetChineseNum("数量","123.45");//得到数量
if (iLen > 16)
{
m_8 = m_9 = "越界错!";
return "";
}
其中
m_8 = m_9 = "越界错!";
是无效代码.
既然是擂台,就要比较.我觉得在可读性,易读性和效率上,我的算法仍然是领先的(鄙视自己一下,又在自夸了).
下面是效率测试,10万次连续转换
using System;
using System.Text;
using System.Text.RegularExpressions;namespace 大写金额转换效率比较
{
class Program
{
static void Main(string[] args)
{
DateTime dt1 = DateTime.Now;
string s1 = "";
string s2="";
for (int i = 0; i < 100000; i++)
{
s1 = SomeStaticClass.GetPrice("100100100001.23"); }
TimeSpan ts = DateTime.Now - dt1; ;
System.Console.WriteLine(s1 + " calcu " + 100000.ToString() + "times elapsed " + ts.TotalMilliseconds.ToString() + "ms");
DateTime dt2 = DateTime.Now;
for (int i = 0; i < 100000; i++)
{
s2 = SomeStaticClass.LGGetPrice("100100100001.23");
}
TimeSpan ts2 = DateTime.Now - dt2; ;
System.Console.WriteLine(s2 + " calcu " + 100000.ToString() + "times elapsed " + ts2.TotalMilliseconds.ToString() + "ms");
}
}
static class SomeStaticClass
{
public static string GetPrice(string sIn)//我为编程狂写的
{
return Regex.Replace(Regex.Replace(Decimal.Parse(sIn).ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A"), @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}"), ".", delegate(Match m) { return "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟萬億兆京垓秭穰"[m.Value[0] - '-'].ToString(); });
}
public static string LGGetPrice(string sIn)//fckadxz写的
{
string s1="";
string s2="";
string s3=""; string numNum = "0123456789.";
string numChina = "零壹贰叁肆伍陆柒捌玖点";
string numChinaWeigh = "个拾佰仟萬拾佰仟亿拾佰仟萬拾佰仟亿"; s1 = (Decimal.Parse(sIn)).ToString("f2");
int iLen = s1.Length;
if (iLen > 16)
{
return "";
}
if (s1.IndexOf('.') > 0)
iLen = s1.IndexOf('.');
//s1:1234->壹贰叁肆
for (int i = 0; i < 11; i++)
{
s1 = s1.Replace(numNum.Substring(i, 1), numChina.Substring(i, 1));
} //s2:佰拾萬仟佰拾个
for (int i = iLen; i >= 1; i--)
{
s2 += numChinaWeigh.Substring(i - 1, 1);
} //s3:s1+s2
for (int i = 0; i < s2.Length; i++)
{
s3 += s1.Substring(i, 1) + s2.Substring(i, 1);
} //s3去"0"后拾佰仟
s3 = s3.Replace("零拾", "零");
s3 = s3.Replace("零佰", "零");
s3 = s3.Replace("零仟", "零"); //s3:00->0,000->0
for (int i = 0; i < iLen; i++)
s3 = s3.Replace("零零", "零"); //s3:去亿,万,个位"0"
s3 = s3.Replace("亿零萬零", "亿零");
s3 = s3.Replace("亿零萬", "亿零");
s3 = s3.Replace("零亿", "亿");
s3 = s3.Replace("零萬", "萬");
if (s3.Length > 2)
s3 = s3.Replace("零个", "个");
s3 = s3.Replace("个", "圆");
if (s1.Substring(s1.Length - 3, 3) != "点零零")
{
s3 += s1.Substring(s1.Length - 2, 2);
s3 = s3.Insert(s3.Length - 1, "角");
s3 += "分";
}
else s3 += "整";
if (s3 != "零圆整")
s3 = s3.Replace("零圆", "");
return s3;
}
}
}
结果是4958ms:2000ms.
我写的程序暂时领先.
using Microsoft.International.Formatters;
using System.Globalization;
using System.Diagnostics;
using System.Text.RegularExpressions;namespace Example_LocalNumericFormat
{
class Program
{
static void Main(string[] args)
{
DateTime dt1 = DateTime.Now;
string s1 = "";
string s2 = "";
string s3 = "";
string sIn = "100100100001";
int iCount = 100000;
for (int i = 0; i < iCount; i++)
{
s1 = SomeStaticClass.GetPrice(sIn); }
TimeSpan ts = DateTime.Now - dt1; ;
System.Console.WriteLine("我为编程狂写的:"+s1 + " calcu " + iCount.ToString() + "times elapsed " + ts.TotalMilliseconds.ToString() + "ms");
DateTime dt2 = DateTime.Now;
for (int i = 0; i < iCount; i++)
{
s2 = SomeStaticClass.LGGetPrice(sIn);
}
TimeSpan ts2 = DateTime.Now - dt2; ;
System.Console.WriteLine("fckadxz 写的:"+s2 + " calcu " + iCount.ToString() + "times elapsed " + ts2.TotalMilliseconds.ToString() + "ms"); DateTime dt3 = DateTime.Now;
for (int i = 0; i < iCount; i++)
{
s3 = SomeStaticClass.MsGetPrice(sIn);
}
TimeSpan ts3 = DateTime.Now - dt3; ;
System.Console.WriteLine("microsoft 写的:"+s3 + " calcu " + iCount.ToString() + "times elapsed " + ts3.TotalMilliseconds.ToString() + "ms");
}
}
static class SomeStaticClass
{
public static string GetPrice(string sIn)//我为编程狂写的
{
return Regex.Replace(Regex.Replace(Decimal.Parse(sIn).ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A"), @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}"), ".", delegate(Match m) { return "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟萬億兆京垓秭穰"[m.Value[0] - '-'].ToString(); });
}
public static string LGGetPrice(string sIn)//fckadxz写的
{
string s1 = "";
string s2 = "";
string s3 = ""; string numNum = "0123456789.";
string numChina = "零壹贰叁肆伍陆柒捌玖点";
string numChinaWeigh = "个拾佰仟萬拾佰仟亿拾佰仟萬拾佰仟亿"; s1 = (Decimal.Parse(sIn)).ToString("f2");
int iLen = s1.Length;
if (iLen > 16)
{
return "";
}
if (s1.IndexOf('.') > 0)
iLen = s1.IndexOf('.');
//s1:1234->壹贰叁肆
for (int i = 0; i < 11; i++)
{
s1 = s1.Replace(numNum.Substring(i, 1), numChina.Substring(i, 1));
} //s2:佰拾萬仟佰拾个
for (int i = iLen; i >= 1; i--)
{
s2 += numChinaWeigh.Substring(i - 1, 1);
} //s3:s1+s2
for (int i = 0; i < s2.Length; i++)
{
s3 += s1.Substring(i, 1) + s2.Substring(i, 1);
} //s3去"0"后拾佰仟
s3 = s3.Replace("零拾", "零");
s3 = s3.Replace("零佰", "零");
s3 = s3.Replace("零仟", "零"); //s3:00->0,000->0
for (int i = 0; i < iLen; i++)
s3 = s3.Replace("零零", "零"); //s3:去亿,万,个位"0"
s3 = s3.Replace("亿零萬零", "亿零");
s3 = s3.Replace("亿零萬", "亿零");
s3 = s3.Replace("零亿", "亿");
s3 = s3.Replace("零萬", "萬");
if (s3.Length > 2)
s3 = s3.Replace("零个", "个");
s3 = s3.Replace("个", "圆");
if (s1.Substring(s1.Length - 3, 3) != "点零零")
{
s3 += s1.Substring(s1.Length - 2, 2);
s3 = s3.Insert(s3.Length - 1, "角");
s3 += "分";
}
else s3 += "整";
if (s3 != "零圆整")
s3 = s3.Replace("零圆", "");
return s3;
}
public static string MsGetPrice(string sIn)//微软的
{
return string.Format(new EastAsiaNumericFormatter(), "{0:L}", Decimal.Parse(sIn));
}
}}
我的算法小小领先.庆祝一下!
微软的算法不是很完善,人家也说了是bata版,可能自己也不太满意.期待他能做的更好.
这也说明,只要专心做事,可以做的甚至比微软要好!和csdn的网友们一起努力!
// 数字转换成大写金额(C#实现)
// 例如:(new Money(200)).ToString() == "贰佰元"
namespace Skyiv.Util
{
using System.Text; class Test
{
static void Main()
{
for (;;)
{
System.Console.Write("金额: ");
string s = System.Console.ReadLine();
decimal m;
try { m = decimal.Parse(s); }
catch { break; }
System.Console.WriteLine("大写: " + new Money(m));
}
}
} // 该类重载的 ToString() 方法返回的是大写金额字符串
class Money
{
public string Yuan = "元"; // “元”,可以改为“圆”、“卢布”之类
public string Jiao = "角"; // “角”,可以改为“拾”
public string Fen = "分"; // “分”,可以改为“美分”之类
static string Digit = "零壹贰叁肆伍陆柒捌玖"; // 大写数字
bool isAllZero = true; // 片段内是否全零
bool isPreZero = true; // 低一位数字是否是零
bool Overflow = false; // 溢出标志
long money100; // 金额*100,即以“分”为单位的金额
long value; // money100的绝对值
StringBuilder sb = new StringBuilder(); // 大写金额字符串,逆序 // 只读属性: "零元"
public string ZeroString
{
get { return Digit[0] + Yuan; }
} // 构造函数
public Money(decimal money)
{
try { money100 = (long)(money * 100m); }
catch { Overflow = true; }
if (money100 == long.MinValue) Overflow = true;
} // 重载 ToString() 方法,返回大写金额字符串
public override string ToString()
{
if (Overflow) return "金额超出范围";
if (money100 == 0) return ZeroString;
string [] Unit = { Yuan, "万", "亿", "万", "亿亿" };
value = System.Math.Abs(money100);
ParseSection(true);
for (int i = 0; i < Unit.Length && value > 0; i++)
{
if (isPreZero && !isAllZero) sb.Append(Digit[0]);
if (i == 4 && sb.ToString().EndsWith(Unit[2]))
sb.Remove(sb.Length - Unit[2].Length, Unit[2].Length);
sb.Append(Unit[i]);
ParseSection(false);
if ((i % 2) == 1 && isAllZero)
sb.Remove(sb.Length - Unit[i].Length, Unit[i].Length);
}
if (money100 < 0) sb.Append("负");
return Reverse();
} // 解析“片段”: “角分(2位)”或“万以内的一段(4位)”
void ParseSection(bool isJiaoFen)
{
string [] Unit = isJiaoFen ?
new string [] { Fen, Jiao } :
new string [] { "", "拾", "佰", "仟" };
isAllZero = true;
for (int i = 0; i < Unit.Length && value > 0; i++)
{
int d = (int)(value % 10);
if (d != 0)
{
if (isPreZero && !isAllZero) sb.Append(Digit[0]);
sb.AppendFormat("{0}{1}", Unit[i], Digit[d]);
isAllZero = false;
}
isPreZero = (d == 0);
value /= 10;
}
} // 反转字符串
string Reverse()
{
StringBuilder sbReversed = new StringBuilder();
for (int i = sb.Length - 1; i >= 0; i--)
sbReversed.Append(sb[i]);
return sbReversed.ToString();
}
}
}
这里贴上网友 我为编程狂 用 正则表达式 写的同样功能程序的连接.他说他用了3天还熬夜,对他这种忘我工作和独辟蹊径表示尊重.
{
static void Main()
{
string s1 = "900000.468";
string s2 = "8000000234";
string sPrice = SomeStaticClass.GetChineseNum("价格", s1);
string sCount = SomeStaticClass.GetChineseNum("数量", s2);
Console.WriteLine("{0}: {1}", s1, sPrice);
Console.WriteLine("{0}: {1}", s2, sCount);
}
}/*
程序输出:
900000.468: 玖拾万圆肆角整
8000000234: 捌拾亿
似乎精度不够。
*/
想来stringbuilder对字符串操作.会快于string的一般操作.
我终于看到了更好的算法!有空了要研究研究.非常高兴,谢谢!
m_1=(float.Parse(strIn)).ToString("f2");
应改用Decimal.Pars代替float.Pars.
{
static void Main()
{
string s1 = "9999999999999.99";
string s2 = "10000000000000";
string sPrice1 = SomeStaticClass.LGGetPrice(s1);
string sPrice2 = SomeStaticClass.LGGetPrice(s2);
System.Console.WriteLine("{0}: {1}", s1, sPrice1);
System.Console.WriteLine("{0}: {1}", s2, sPrice2);
}
}
/*
不错,16楼的程序已经不会丢失精度了:
9999999999999.99: 玖萬玖仟玖佰玖拾玖亿玖仟玖佰玖拾玖萬玖仟玖佰玖拾玖圆玖角玖分
10000000000000:
看来只能处理13位整数。
*/
if (iLen > 16) //iLen包含了小数点和2位小数,所以被限定13位整数.但这个程序要调整精度却非常简单.
{
return "";
}
和if (iLen > 16) //可以改变16到更大的数字.
{
return "";
}就可以实现精度扩展
{
string s1 = "";
string s2 = "";
string s3 = ""; string numNum = "0123456789.";
string numChina = "零壹贰叁肆伍陆柒捌玖点";
string numChinaWeigh = "个拾佰仟萬拾佰仟亿拾佰仟萬拾佰仟亿拾佰仟萬拾佰仟亿拾佰仟萬拾佰仟亿"; s1 = (Decimal.Parse(sIn)).ToString("f2");
int iLen = s1.Length;
if (iLen > 32)
{
return "";
}
if (s1.IndexOf('.') > 0)
iLen = s1.IndexOf('.');
//s1:1234->壹贰叁肆
for (int i = 0; i < 11; i++)
{
s1 = s1.Replace(numNum.Substring(i, 1), numChina.Substring(i, 1));
} //s2:佰拾萬仟佰拾个
for (int i = iLen; i >= 1; i--)
{
s2 += numChinaWeigh.Substring(i - 1, 1);
} //s3:s1+s2
for (int i = 0; i < s2.Length; i++)
{
s3 += s1.Substring(i, 1) + s2.Substring(i, 1);
} //s3去"0"后拾佰仟
s3 = s3.Replace("零拾", "零");
s3 = s3.Replace("零佰", "零");
s3 = s3.Replace("零仟", "零"); //s3:00->0,000->0
for (int i = 0; i < iLen; i++)
s3 = s3.Replace("零零", "零"); //s3:去亿,万,个位"0"
s3 = s3.Replace("亿零萬零", "亿零");
s3 = s3.Replace("亿零萬", "亿零");
s3 = s3.Replace("零亿", "亿");
s3 = s3.Replace("零萬", "萬");
if (s3.Length > 2)
s3 = s3.Replace("零个", "个");
s3 = s3.Replace("个", "圆");
if (s1.Substring(s1.Length - 3, 3) != "点零零")
{
s3 += s1.Substring(s1.Length - 2, 2);
s3 = s3.Insert(s3.Length - 1, "角");
s3 += "分";
}
else s3 += "整";
if (s3 != "零圆整")
s3 = s3.Replace("零圆", "");
return s3;
}
我这个用正则表达式 3 行转换的,能实现四舍五入,能转 decimal 最大值。详细说明见
http://topic.csdn.net/u/20080125/09/04c65875-4f50-42cd-bd63-d7b1429e42e1.html
31楼-33楼
using System;
using System.Text.RegularExpressions;class Program
{
static void Main()
{
string s = (new Random().Next()/100.0).ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
string d = Regex.Replace(s, @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
Console.WriteLine(d + "\n" + Regex.Replace(d, ".", delegate(Match m) { return "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟萬億兆京垓秭穰"[m.Value[0] - '-'].ToString(); }));
}
}
.0448ms(自微软源码改编)
fckadxz 写的:壹仟零壹亿零壹拾萬零壹圆整 calcu 100000times elapsed 5618
.0784ms
空间Ⅳ 写的:壹仟零壹亿零壹拾万零壹元 calcu 100000times elapsed 1251
.8ms 还是没有空间Ⅳ的快,不过我是一直用128位的 decimal 计算,而空间Ⅳ用64位的 long,计算范围大,如果也改成 64 位的long,应该能更快,能达到这个速度说明代码很成功。微软的核心代码不论架构还是效率都非常的高。但最后由于外层的派生类提供多语言支持等原因损失了些性能。楼主不要轻易拿自己 56 秒的代码说比微软的 14 秒的代码还快。
{
long d = long.Parse(sIn);
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "仟亿拾佰仟萬拾佰";
StringBuilder sb = new StringBuilder();
int[] iWeight = new int[sIn.Length];
int[] iValue = new int[sIn.Length];
for (int i = 0; i < sIn.Length; i++)
{
iWeight[i] = (sIn.Length - i) % 8;
iValue[sIn.Length - i - 1] = (int)(d % 10);
d = d / 10;
}
int iCount = 1;
int iNext = 0;
for (int i = 0; i < sIn.Length; i++)
{
if (sIn[i] > '0')
{
sb.Append(sNum[iValue[i]]);
if (i < sIn.Length - 1)
sb.Append(sWeight[iWeight[i]]);
iNext = i + 1;
}
else if (iWeight[i] == 1)
{
if (i < sIn.Length - 1)
sb.Append("亿");
else
break;
}
else if (iWeight[i] == 5 && (i < 4 || sIn.Substring(i - 3, 4) != "0000"))
sb.Append("万");
else if (i < iNext)
continue;
else //处理出现的连续0的第一个0
{
iCount = 1;
for (int j = i + 1; j < sIn.Length; j++)
{
if (iValue[j] == 0 && iWeight[j] != 0)
{
iCount++;
continue;
}
else
break;
}
iNext = i + iCount; if (iWeight[i] == 0)//千万
{
if (iCount == 8)
continue;
else
sb.Append("零");
}
else if (iWeight[i] == 7)//百万
{
if (iCount == 3)
continue;
else
sb.Append("零");
}
else if (iWeight[i] == 6)//十万
{
if (iCount == 2)
continue;
else
sb.Append("零");
}
else if (iWeight[i] == iCount)//千百十
continue;
else
sb.Append("零");
}
}
return sb.ToString();
}
public static string GetNumFromLeft2Right(string sIn)//fckadxz 2008 写的
{
long d = long.Parse(sIn);
if (d == 0)
return "零";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "仟亿拾佰仟萬拾佰";
StringBuilder sb = new StringBuilder();
int[] iWeight = new int[sIn.Length];
int[] iValue = new int[sIn.Length];
for (int i = 0; i < sIn.Length; i++)
{
iWeight[i] = (sIn.Length - i) % 8;
iValue[sIn.Length - i - 1] = (int)(d % 10);
d = d / 10;
}
int iCount = 1;
int iNext = 0;
for (int i = 0; i < sIn.Length; i++)
{
if (sIn[i] > '0')
{
sb.Append(sNum[iValue[i]]);
if (i < sIn.Length - 1)
sb.Append(sWeight[iWeight[i]]);
iNext = i + 1;
}
else if (iWeight[i] == 1)
{
if (i < sIn.Length - 1)
sb.Append("亿");
}
else if (iWeight[i] == 5 )
{
if(i < 4 || sIn.Substring(i - 3, 4) != "0000")
sb.Append("萬");
}
else if (i < iNext)
continue;
else //处理出现的连续0的第一个0
{
iCount = 1;
for (int j = i + 1; j < sIn.Length && iValue[j] == 0 && iWeight[j] != 0; j++)
iCount++;
iNext = i + iCount; if (iWeight[i] == 0)//千万
{
if (iCount != 8)
sb.Append("零");
}
else if (iWeight[i] == 7)//百万
{
if (iCount != 3)
sb.Append("零");
}
else if (iWeight[i] == 6)//十万
{
if (iCount != 2)
sb.Append("零");
}
else if (iWeight[i] != iCount)//千百十
sb.Append("零");
}
}
return sb.ToString();
}
{
long d = long.Parse(sIn);
if (d == 0)
return "零";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "仟亿拾佰仟萬拾佰";
StringBuilder sb = new StringBuilder();
int[] iWeight = new int[sIn.Length];
int[] iValue = new int[sIn.Length];
for (int i = 0; i < sIn.Length; i++)
{
iWeight[i] = (sIn.Length - i) % 8;
iValue[sIn.Length - i - 1] = (int)(d % 10);
d = d / 10;
}
int iCount = 1;
int iNext = 0;
bool bZeroAfterWan = false;
for (int i = 0; i < sIn.Length; i++)
{
if (sIn[i] > '0')
{
sb.Append(sNum[iValue[i]]);
if (i < sIn.Length - 1)
sb.Append(sWeight[iWeight[i]]);
iNext = i + 1;
}
else if (iWeight[i] == 1)
{
if (i < sIn.Length - 1)
sb.Append("亿");
}
else if (iWeight[i] == 5)
{
if (i < 4 || iValue[i - 3] + iValue[i - 2] + iValue[i - 1] > 0)
{
sb.Append("萬");
if (bZeroAfterWan)
{
sb.Append("零");
bZeroAfterWan = false;
}
}
}
else if (i < iNext)
continue;
else //处理出现的连续0的第一个0
{
iCount = 1;
for (int j = i + 1; j < sIn.Length && iValue[j] == 0 && iWeight[j] != 0; j++)
iCount++;
iNext = i + iCount; if (iWeight[i] == 0)//千万
{
if (iCount != 8)
sb.Append("零");
}
else if (iWeight[i] == 7)//百万
{
if (iCount < 3)
sb.Append("零");
if (iCount > 3)
bZeroAfterWan = true;
}
else if (iWeight[i] == 6)//十万
{
if (iCount < 2)
sb.Append("零");
if (iCount > 2)
bZeroAfterWan = true;
}
else if (iWeight[i] != iCount)//千百十
sb.Append("零");
}
}
return sb.ToString();
}
{
long d = long.Parse(sIn);
if (d == 0)
return "零";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "仟亿拾佰仟万拾佰";
StringBuilder sb = new StringBuilder();
int[] iWeight = new int[sIn.Length];
int[] iValue = new int[sIn.Length];
int iCount = 0;
int iNext = 0;
for (int i = 0; i < sIn.Length; i++)
{
iWeight[i] = (sIn.Length - i) % 8;
iValue[sIn.Length - i - 1] = (int)(d % 10);
d = d / 10;
}
for (int i = 0; i < sIn.Length; i++)
{
if (sIn[i] > '0')
{
sb.Append(sNum[iValue[i]]);
if (i < sIn.Length - 1)
sb.Append(sWeight[iWeight[i]]);
iNext = i + 1;
}
else if (iWeight[i] == 1)
{
if (i < sIn.Length - 1)
sb.Append("亿");
iNext = i + 1;
}
else if (iWeight[i] == 5)
{
if (i < 4 || iValue[i - 3] + iValue[i - 2] + iValue[i - 1] > 0)
{
sb.Append("万");
if(i> iNext-5 && i<iNext -1 )
sb.Append("零");
else
iNext = i + 1;
}
}
else if (i == iNext)//处理出现的连续0的第一个0
{
iCount = 1;
for (int j = i + 1; j < sIn.Length && iValue[j] == 0 && iWeight[j] != 0; j++)
iCount++;
iNext = i+iCount;
if (iWeight[i] == 0)//千万
{
if (iCount != 8)
sb.Append("零");
}
else if (iWeight[i] == 7)//百万
{
if (iCount < 3)
sb.Append("零");
}
else if (iWeight[i] == 6)//十万
{
if (iCount < 2)
sb.Append("零");
}
else if (iWeight[i] != iCount)//千百十
sb.Append("零");
}
}
return sb.ToString();
}
{
//采用从左到右,直接读出的办法 fckadxz 2008
private static string GetInt (string sIn)
{
long d = long.Parse(sIn);
if (d == 0)
return "零";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "仟亿拾佰仟万拾佰";
StringBuilder sb = new StringBuilder();
int[] iWeight = new int[sIn.Length];
int[] iValue = new int[sIn.Length];
int iCount = 0;
int iNext = 0;
for (int i = 0; i < sIn.Length; i++)
{
iWeight[i] = (sIn.Length - i) % 8;
iValue[sIn.Length - i - 1] = (int)(d % 10);
d = d / 10;
}
for (int i = 0; i < sIn.Length; i++)
{
if (sIn[i] > '0')
{
sb.Append(sNum[iValue[i]]);
if (i < sIn.Length - 1)
sb.Append(sWeight[iWeight[i]]);
iNext = i + 1;
}
else if (iWeight[i] == 1)
{
if (i < sIn.Length - 1)
sb.Append("亿");
iNext = i + 1;
}
else if (iWeight[i] == 5)
{
if (i < 4 || iValue[i - 3] + iValue[i - 2] + iValue[i - 1] > 0)
{
sb.Append("万");
if (i > iNext - 5 && i < iNext - 1)
sb.Append("零");
else
iNext = i + 1;
}
}
else if (i == iNext)//处理出现的连续0的第一个0
{
iCount = 1;
for (int j = i + 1; j < sIn.Length && iValue[j] == 0 && iWeight[j] != 0; j++)
iCount++;
iNext = i + iCount;
if (iWeight[i] == 0)//千万
{
if (iCount != 8)
sb.Append("零");
}
else if (iWeight[i] == 7)//百万
{
if (iCount < 3)
sb.Append("零");
}
else if (iWeight[i] == 6)//十万
{
if (iCount < 2)
sb.Append("零");
}
else if (iWeight[i] != iCount)//千百十
sb.Append("零");
}
}
return sb.ToString();
}
private static string GetReal (string sIn)
{
double f = double.Parse(sIn);
if (f == 0)
return "";
string sNum = "零壹贰叁肆伍陆柒捌玖";
StringBuilder sb = new StringBuilder();
int[] iValue = new int[sIn.Length - 2];
for (int i = 0; i < sIn.Length - 2;i++ )
{
iValue[i] = (int)((f * Math.Pow(10, i + 1)) % 10);
}
sb.Append("点");
for (int i = 0; i < sIn.Length-2; i++)
{
sb.Append(sNum[iValue[i]]);
}
return sb.ToString();
}
private static string GetRealPrice(string sIn)
{
double f = double.Parse(sIn);
if (f == 0)
return "圆整";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "角分";
StringBuilder sb = new StringBuilder();
int[] iValue = new int[2];
for (int i = 0; i < 2; i++)
iValue[i] = (int)((f * Math.Pow(10, i + 1)) % 10);
sb.Append("圆");
sb.Append(sNum[iValue[0]]);
if (iValue[0] > 0)
sb.Append(sWeight[0]);
if (iValue[1] > 0)
{
sb.Append(sNum[iValue[1]]);
sb.Append(sWeight[1]);
}
else
{
sb.Append("整");
}
return sb.ToString();
}
public static string GetCount (string sIn)
{
decimal f = decimal.Parse(sIn);
long d = (long)f;
decimal f2 = f - d;
return GetInt(d.ToString ())+ GetReal(f2.ToString ());;
}
public static string GetPrice ( string sIn)
{
decimal f = decimal.Parse(sIn);
long d = (long)f;
decimal f2 = f - d;
return GetInt(d.ToString()) + GetRealPrice(f2.ToString("f2")); ;
}
}
你这用 long 拼起来的程序是很失败的,虽然貌似速度很快,可是毫无设计思想可言,在此基础上很难扩充,达到微软那种功能,例如多国货币规格的支持,(国内兆为一亿亿,日韩兆为一万亿),更别提decimal数字支持。能实现也是一身补丁。
而且你引以为豪的速度并没有快过微软的程序,只是你投机取巧用 long 数据比 decimal 小的特点造成的假象,我把微软的源码核心提取出来,改成long版本的,给你看看什么叫优秀的程序,因为要兼容你的参数设定,效率和安全性都完了,不过还是比你楼上的垃圾代码快很多。
using System;
using System.Globalization;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Text;class Program
{
static void Main(string[] args)
{
DateTime dt1 = DateTime.Now;
string s1 = "";
string s2 = "";
Stack<char> s3=new Stack<char>(0) ;
string sIn = "1001001000001";
//string sIn = "1.995";
decimal d = decimal.MaxValue;
int iCount = 100000; DateTime dt2 = DateTime.Now;
for (int i = 0; i < iCount; i++)
{
s2 = SomeStaticClass.GetPrice(sIn);
}
TimeSpan ts2 = DateTime.Now - dt2; ;
System.Console.WriteLine("fckadxz 写的:" + s2 + " calcu " + iCount.ToString() + "times elapsed " + ts2.TotalMilliseconds.ToString() + "ms"); DateTime dt3 = DateTime.Now;
for (int i = 0; i < iCount; i++)
{
s3 = RMB.DecimalFormatter(sIn);
}
TimeSpan ts3 = DateTime.Now - dt3; ;
System.Console.WriteLine("microsoft 写的:" + new string(s3.ToArray()) + " calcu " + iCount.ToString() + "times elapsed " + ts3.TotalMilliseconds.ToString() + "ms");
Console.ReadKey();
}
}
{
//采用从左到右,直接读出的办法 fckadxz 2008
private static string GetInt(string sIn)
{
long d = long.Parse(sIn);
if (d == 0)
return "零";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "仟亿拾佰仟万拾佰";
StringBuilder sb = new StringBuilder();
int[] iWeight = new int[sIn.Length];
int[] iValue = new int[sIn.Length];
int iCount = 0;
int iNext = 0;
for (int i = 0; i < sIn.Length; i++)
{
iWeight[i] = (sIn.Length - i) % 8;
iValue[sIn.Length - i - 1] = (int)(d % 10);
d = d / 10;
}
for (int i = 0; i < sIn.Length; i++)
{
if (sIn[i] > '0')
{
sb.Append(sNum[iValue[i]]);
if (i < sIn.Length - 1)
sb.Append(sWeight[iWeight[i]]);
iNext = i + 1;
}
else if (iWeight[i] == 1)
{
if (i < sIn.Length - 1)
sb.Append("亿");
iNext = i + 1;
}
else if (iWeight[i] == 5)
{
if (i < 4 || iValue[i - 3] + iValue[i - 2] + iValue[i - 1] > 0)
{
sb.Append("万");
if (i > iNext - 5 && i < iNext - 1)
sb.Append("零");
else
iNext = i + 1;
}
}
else if (i == iNext)//处理出现的连续0的第一个0
{
iCount = 1;
for (int j = i + 1; j < sIn.Length && iValue[j] == 0 && iWeight[j] != 0; j++)
iCount++;
iNext = i + iCount;
if (iWeight[i] == 0)//千万
{
if (iCount != 8)
sb.Append("零");
}
else if (iWeight[i] == 7)//百万
{
if (iCount < 3)
sb.Append("零");
}
else if (iWeight[i] == 6)//十万
{
if (iCount < 2)
sb.Append("零");
}
else if (iWeight[i] != iCount)//千百十
sb.Append("零");
}
}
return sb.ToString();
}
private static string GetReal(string sIn)
{
double f = double.Parse(sIn);
if (f == 0)
return "";
string sNum = "零壹贰叁肆伍陆柒捌玖";
StringBuilder sb = new StringBuilder();
int[] iValue = new int[sIn.Length - 2];
for (int i = 0; i < sIn.Length - 2; i++)
{
iValue[i] = (int)((f * Math.Pow(10, i + 1)) % 10);
}
sb.Append("点");
for (int i = 0; i < sIn.Length - 2; i++)
{
sb.Append(sNum[iValue[i]]);
}
return sb.ToString();
}
private static string GetRealPrice(string sIn)
{
double f = double.Parse(sIn);
if (f == 0)
return "圆整";
string sNum = "零壹贰叁肆伍陆柒捌玖";
string sWeight = "角分";
StringBuilder sb = new StringBuilder();
int[] iValue = new int[2];
for (int i = 0; i < 2; i++)
iValue[i] = (int)((f * Math.Pow(10, i + 1)) % 10);
sb.Append("圆");
sb.Append(sNum[iValue[0]]);
if (iValue[0] > 0)
sb.Append(sWeight[0]);
if (iValue[1] > 0)
{
sb.Append(sNum[iValue[1]]);
sb.Append(sWeight[1]);
}
else
{
sb.Append("整");
}
return sb.ToString();
}
public static string GetCount(string sIn)
{
decimal f = decimal.Parse(sIn);
long d = (long)f;
decimal f2 = f - d;
return GetInt(d.ToString()) + GetReal(f2.ToString()); ;
}
public static string GetPrice(string sIn)
{
decimal f = decimal.Parse(sIn);
long d = (long)f;
decimal f2 = f - d;
return GetInt(d.ToString()) + GetRealPrice(f2.ToString("f2")); ;
}
}static class RMB
{
private static readonly string DigitText = "零壹贰叁肆伍陆柒捌玖";
private static readonly string PositionText = "圆拾佰仟萬億兆京垓秭穰";
private static readonly string OtherText = "分角整负"; private static void GetFractionStack(int num, Stack<char> stack)
{
int fen, jiao = Math.DivRem(num, 10, out fen);
if (fen != 0)
{
stack.Push(OtherText[0]);
stack.Push(DigitText[fen]);
}
if (jiao != 0)
{
stack.Push(OtherText[1]);
stack.Push(DigitText[jiao]);
}
}
private static void GetIntegerStack(long num, int position, Stack<char> stack)
{
if (num < 10000L)
{
int _num = (int)num;
for (int i = 0, mod_10 = 0; i < 4; i++)
{
bool behindZero = mod_10 == 0;
_num = Math.DivRem(_num, 10, out mod_10);
if (mod_10 == 0)
{
if (behindZero)
if (_num == 0)
break;
else
continue;
}
else if (i > 0)
stack.Push(PositionText[i]);
stack.Push(DigitText[mod_10]);
}
}
else
{
GetIntegerStack(num % 10000L, position, stack);
int mask = -1, offset = 4;
while ((position & (0x1 << ++mask)) == 0) ;
mask += offset;
while (stack.Peek() == PositionText[offset++])
stack.Pop();
stack.Push(PositionText[mask]);
GetIntegerStack(num / 10000L, position + 1, stack);
}
}
public static Stack<char> DecimalFormatter(string input)
{
decimal d = decimal.Parse(input) + 0.005M;
bool isNegate = input[0] == '-';
long integer = decimal.ToInt64(d);
int fraction = decimal.ToInt32((d - integer) * 100M);
Stack<char> stack = new Stack<char>(60);
if (fraction == 0)
stack.Push(OtherText[2]);
else
GetFractionStack(fraction, stack);
if (integer != 0L)
{
stack.Push(PositionText[0]);
GetIntegerStack(integer, 1, stack);
if (stack.Peek() == DigitText[0])
stack.Pop();
}
else if (fraction == 0)
{
stack.Push(PositionText[0]);
stack.Push(DigitText[0]);
}
if (isNegate)
stack.Push(OtherText[3]);
return stack;
}
}
// "1.995";
//fckadxz 写的:壹圆零整 calcu 100000times elapsed 1271.8288ms
//microsoft 写的:贰圆整 calcu 100000times elapsed 450.648ms
// "1001001000001"
//fckadxz 写的:壹万零壹拾亿零壹佰万零壹圆整 calcu 100000times elapsed 1582.2752ms
//microsoft 写的:壹萬零壹拾億零壹佰萬零壹圆整 calcu 100000times elapsed 801.152ms
感谢 IV空间\我为编程狂还有其他网友 的积极参与.使我从中学到了不少.
color=#0000FF]最精简的代码和最快的代码都是我写的[/color]
这是你的代码吗?有没有知识产权的概念?反编译的代码是不能随便用的,有时还是违法的.
不尊重别人的劳动成果,毛主席说过,是要不得的.
发表于:2008-01-28 06:10:3035楼 得分:0
这个代码的字符串操作借鉴了 空间IV 的,但是整体算法完全不同.又把效率提高了一大截.
你这不是也在“借鉴”。 下面这段就是我说的微软的源码,和我的代码差别非常大吧。我也只是“借鉴”了递归架构,其他代码都是我自己写出来的。不信你可以把下面这段代码和我写的比较一下,假如你能看得懂我的代码的话。http://topic.csdn.net/u/20080125/09/04c65875-4f50-42cd-bd63-d7b1429e42e1.html 53楼
你说返回值要转成字符串比较才公平,谁说的?我还觉得大家都返回 Stack 集合或字符数组测试速度才公平。
微软的程序向来层次分明。核心算法返回数组或集合形式的,界面层算法才转用户需要的字符串,这样便于日后程序的功能扩充和维护,例如用户可能需要“整”,可能不需要。这就可以在界面层操作而非核心层。
如果是你一定在核心算法里增加 if 语句,把核心算法搞成补丁铺。像你那种不分层的浑然一体的结构,最后只能落得个全身补丁的下场。我倒是想把你的返回值改成比较优势的数组形式,可惜那样你得程序就变得更慢了。
另外返回字符集合而非字符串给界面层的好处是显而易见的,操作字符串带来的系统消耗比操作数组大的多,你可能理解不了,不过你改了我的返回值为字符串后速度明显下降,应该能明白这种消耗吧。
假如微软雇佣我们俩单独完成整个 EastAsiaNumericFormatter ,你的程序如果不分层,肯定满是补丁,维护困难。如果分层,在各层间用字符串传递,效率受很大影响,最终只能落后于我。况且我写的就是转字符串也快过你的,更别提你难以解决的跨小数点四舍五入错误和万亿以上的单位错误。还有 Console 可以直接输出 Char[],为了照顾你得阅读习惯,我才转成 string 形式。protected virtual void GetIntegralStack(decimal num, ulong position, StackWithIndex stack)
{
if (num < 10000M)
{
if ((num != 0M) || (position == 0xe8d4a51000L))
{
stack.Push(this.GetPositionText(position));
}
for (int i = 0; i < 4; i++)
{
int digit = (int) decimal.op_Modulus(num, 10M);
ulong num4 = (ulong) Math.Pow(10.0, (double) i);
num /= 10M;
stack.Push(this.GetDigitText(digit, num4));
}
}
else
{
this.GetIntegralStack(Math.Truncate(decimal.op_Modulus(num, 10000M)), position, stack);
this.GetIntegralStack(Math.Truncate((decimal) (num / 10000M)), position * ((ulong) 0x2710L), stack);
}
}
using System.Collections.Generic;
using System.Text;
namespace 大写5
{
class Program
{
static void Main(string[] args)
{
Stack<char> stack = new Stack<char>();
string sIn = "12222000000000000000000001.34";
int iCount = 100000;
DateTime dt2 = DateTime.Now;
for (int i = 0; i < iCount; i++)
{
stack = SomeStaticClass.GetPrice2(sIn);
}
TimeSpan ts2 = DateTime.Now - dt2; ;
System.Console.WriteLine("fckadxz 2008 无限版:" + new string(stack.ToArray()) + " calcu " + iCount.ToString() + "times elapsed " + ts2.TotalMilliseconds.ToString() + "ms"); Console.ReadKey();
}
}
static class SomeStaticClass
{
private static Dictionary<char, char> dn = new Dictionary<char, char>();
static SomeStaticClass()
{
dn.Add('1', '壹');
dn.Add('2', '贰');
dn.Add('3', '叁');
dn.Add('4', '肆');
dn.Add('5', '伍');
dn.Add('6', '陆');
dn.Add('7', '柒');
dn.Add('8', '捌');
dn.Add('9', '玖');
dn.Add('0', '零');
}
private static readonly string sNumFenJiaoYuan = "分角圆整";
private static readonly string sNum = "零壹贰叁肆伍陆柒捌玖";
private static readonly char cZero = '零';
private static readonly char cWan = '万';
private static readonly char cYi = '亿';
private static readonly string sWeight = "仟亿拾佰仟万拾佰";
//fckadxz 2008 精度无限制版(甚至1000万位!),你可以 这样调用
//SomeStaticClass.GetPrice2("10000000000000000000000000000000000000000001.23")
internal static Stack<char> GetPrice2(string sIn)//使用 xxxxx.xx的格参数格式 x范围0-9
{
Stack<char> chStack = new Stack<char>();
int iLen = sIn.Length - 3;
int iError = -1;
int iZero = 0;
int iZeroAll = 0;
//检查数据
for (int i = 0; i < sIn.Length; i++)
{
if (i == iLen)
{
if (sIn[i] != '.')
{
iError = i + 1;
break;
}
}
else if (sIn[i] < '0' || sIn[i] > '9')
{
iError = i + 1;
break;
}
}
if (iError >= 0)
throw new Exception("数据错误出现在 \r\n" + sIn + " \r\n第" + iError + "位置!");
//分
char c = sIn[sIn.Length - 1];
if (c == '0')
{
chStack.Push(sNumFenJiaoYuan[3]);
iZero++;
}
else
{
chStack.Push(sNumFenJiaoYuan[0]);
chStack.Push(dn[c]);
}
//角
c = sIn[sIn.Length - 2];
if (c == '0')
{
if (iZero == 0)
chStack.Push(dn[c]);
}
else
{
chStack.Push(sNumFenJiaoYuan[1]);
chStack.Push(dn[c]);
}
//整数部分
iZero = 0; chStack.Push(sNumFenJiaoYuan[2]);
int iw = 1;
for (int i = iLen - 1; i >= 0; i--, iw++)
{
if (iw == 8)
iw = 0;
c = sIn[i];
if (c > '0')
{
if (iZero > 0)
{
if (iw == 1)//亿
{
if (iZero != 8)
chStack.Push(cZero);
}
else if (iw == 2)//十
{ }
else if (iw == 3)//百
{
if (iZero < 2)
chStack.Push(cZero);
}
else if (iw == 4)//千
{
if (iZero < 3)
chStack.Push(cZero);
}
else if (iw == 5)//万
{
if (iZero < 4)
chStack.Push(cZero);
}
else if (iw == 6)//十万
{
if (iZero != 5 && iZero != 1)
chStack.Push(cZero);
chStack.Push(cWan);
}
else if (iw == 7)//百万
{
if (iZero == 2)
{
chStack.Push(cWan);
}
else if (iZero > 2)
{
if (iZero != 6)
chStack.Push(cZero);
chStack.Push(cWan); }
else
{
chStack.Push(cZero);
}
}
else if (iw == 0)//千万
{
if (iZero == 3)
{
chStack.Push(cWan);
}
else if (iZero > 3)
{
if (iZero != 7)
chStack.Push(cZero);
chStack.Push(cWan);
}
else
{
chStack.Push(cZero);
}
}
}
iZero = 0;
if (i < iLen - 1)
chStack.Push(sWeight[iw]);
chStack.Push(dn[c]);
}
else
{
if (iw == 1)//亿和个位
{ if (i < iLen - 1)
{
if (iZero < 8)
chStack.Push(cZero);
chStack.Push(cYi);
}
iZero = 1;
}
else
iZero++;
iZeroAll++;
}
}
if (iZeroAll == iLen)
chStack.Push(cZero);
return chStack;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Math.Round(1.5));
Console.WriteLine(Math.Round(2.5));
Console.WriteLine(string.Format("{0:F0}", 1.5));
Console.WriteLine(string.Format("{0:F0}", 2.5));
}
}[code]真是的,浪费我时间给你上课,交学费昂
Round 方法默认行为:当一个数字是其他两个数字的中间值时,会将其舍入为最接近的偶数。
decimal 也不过 28 位,可以对应每一位写几句处理代码,从右往左顺序处理下来,没有循环,没有嵌套,没有回溯操作,那样最快。
[align=center]第一部分 会计基本知识与基本技能一、汉字书写和会计大写数字[/align]4.特别是注意练好表示数额多少的那些汉字,尽可能的达到合乎标准写法且书写特别流
利。一般讲,财会工作中除运用阿拉伯字书写数额外,不少地方需要用汉字来表示金额,如,书写借条时,不仅要看清阿拉伯字数额(小写),而且要运用汉字书写金额(大写),两者缺一不可。从一般情况看,书写金额的汉字应使用会计体汉字,即:零壹贰叁肆伍陆柒捌玖拾佰仟万亿等大写数字,不应使用“另(或令)、一、二、三、四、五、六、七、八、九、十、百、千”等汉字;更不能用谐音字替代会计体数字。非经国务院公布的简体字及地方约定俗成的不规范汉字,理应不要会计记录中出现。除此之外,在行文中表示数额的同一行相邻数字之间,最好要空出半个汉字大写的位置,以示区别。汉字数码标准字体如下:
零 壹 贰 叁 肆 伍 陆 柒 捌 玖 拾 佰 仟 万 亿看来国务院好像没公布“兆”等字,那个“等”的意思看来国务院还没给出来。所以你说亿亿是对的,冤枉你了,不好意思。
fckadxz 2008 无限版:零圆壹角整
这怎么看着这么别扭
using System;
using System.Collections.Generic;
namespace 大写5
{
class Program
{
static void Main(string[] args)
{
Stack <char> stack = new Stack<char>();
string sIn = "999000999.45";
int iCount = 100000;
DateTime dt2 = DateTime.Now;
for (int i = 0; i < iCount; i++)
{
stack = SomeStaticClass.GetPrice2(sIn);
}
TimeSpan ts2 = DateTime.Now - dt2; ;
Console.WriteLine("fckadxz 2008 无限版:");
Console.WriteLine(sIn);
Console.WriteLine(new string(stack.ToArray()));
Console.WriteLine("trans "+iCount+ " times,elapsed " + ts2.TotalMilliseconds.ToString() + " ms");
Console.ReadKey();
}
}
static class SomeStaticClass
{
private static Dictionary<char, char> dn = new Dictionary<char, char>();
static SomeStaticClass()
{
dn.Add('1', '壹');
dn.Add('2', '贰');
dn.Add('3', '叁');
dn.Add('4', '肆');
dn.Add('5', '伍');
dn.Add('6', '陆');
dn.Add('7', '柒');
dn.Add('8', '捌');
dn.Add('9', '玖');
dn.Add('0', '零');
}
private static readonly string sNumFenJiaoYuan = "分角圆整";
private static readonly char cZero = '零';
private static readonly char cWan = '万';
private static readonly char cYi = '亿';
private static readonly string sWeight = "仟亿拾佰仟万拾佰";
//fckadxz 2008 精度无限制版(甚至1000万位!),你可以 这样调用
//SomeStaticClass.GetPrice2("100000001.23")
//使用 m.xx的格参数格式 m:>=0的整数, x范围0-9,小数点左边大于等于1位,小数点右刚好2位
internal static Stack<char> GetPrice2(string sIn)
{
Stack<char> chStack = new Stack<char>();
int iLen = sIn.Length - 3;
int iZero = 0;
string strErrow = "";
bool bZeroYuan = false;
bool bZeroJiao = false;
bool bZeroFen= false; if (sIn.Length < 4)
strErrow = "输入数据不对!输入字符串至少4个字符(小数点左1位,小数点1位,小数右2位).";
//检查数据
for (int i = 0; i < sIn.Length && strErrow .Length == 0; i++)
{
if(i==0 && iLen >1)
{
if(sIn[i] < '1' || sIn[i] > '9')
strErrow = "左起第1位字符错误,该字符是"+sIn [i];
}
else if (i == iLen)
{
if (sIn[i] != '.')
strErrow = "左起第" + (i + 1) + "位字符错误,该字符是 '" + sIn[i]+"',此位应该是小数点";
}
else if (sIn[i] < '0' || sIn[i] > '9')
{
strErrow = "左起第" + (i + 1) + "位字符错误,该字符是" + sIn[i];
}
}
if (strErrow .Length>0)
throw new Exception("\r\n"+strErrow );
if (iLen == 1)
{
bZeroYuan = sIn[0] == '0';
bZeroJiao = sIn[2] == '0';
bZeroFen = sIn[3] == '0';
if (bZeroYuan && bZeroJiao && bZeroFen)//零元整
{
chStack.Push(sNumFenJiaoYuan[3]);
chStack.Push(sNumFenJiaoYuan[2]);
chStack.Push(cZero);
return chStack;
}
}
//分
char c = sIn[sIn.Length - 1];
if (c == '0')
{
chStack.Push(sNumFenJiaoYuan[3]);
iZero++;
}
else
{
chStack.Push(sNumFenJiaoYuan[0]);
chStack.Push(dn[c]);
}
//角
c = sIn[sIn.Length - 2];
if (c == '0')
{
if (iZero == 0 && bZeroYuan == false )
chStack.Push(cZero);
}
else
{
chStack.Push(sNumFenJiaoYuan[1]);
chStack.Push(dn[c]);
}
if (bZeroYuan == true)
return chStack; //整数部分
iZero = 0;
chStack.Push(sNumFenJiaoYuan[2]);
int iw = 1;
for (int i = iLen - 1; i >= 0; i--, iw++)
{
if (iw == 8)
iw = 0;
c = sIn[i];
if (c > '0')
{
if (iZero > 0)
{
switch (iw)
{
case 1://亿
if (iZero != 8)
chStack.Push(cZero);
break ;
case 2://十
break ;
case 3://百
if (iZero < 2)
chStack.Push(cZero);
break;
case 4://千
if (iZero < 3)
chStack.Push(cZero);
break;
case 5://万
if (iZero < 4)
chStack.Push(cZero);
break;
case 6://十万
if (iZero != 5 && iZero != 1)
chStack.Push(cZero);
chStack.Push(cWan);
break;
case 7://百万
if (iZero == 2)
{
chStack.Push(cWan);
}
else if (iZero > 2)
{
if (iZero != 6)
chStack.Push(cZero);
chStack.Push(cWan); }
else
{
chStack.Push(cZero);
}
break;
case 0://千万
if (iZero == 3)
{
chStack.Push(cWan);
}
else if (iZero > 3)
{
if (iZero != 7)
chStack.Push(cZero);
chStack.Push(cWan);
}
else
{
chStack.Push(cZero);
}
break;
}
}
iZero = 0;
if (i < iLen - 1)
chStack.Push(sWeight[iw]);//因为不是0且不是个位 有权
chStack.Push(dn[c]);//因为不是0 有数字
}
else
{
if (iw == 1)//亿和个位
{
if (i < iLen - 1)
{
if (iZero < 8)
chStack.Push(cZero);
chStack.Push(cYi);
}
iZero = 1;
}
else
iZero++;
}
}
return chStack;
}
}
}
对于参数问题,我的看法是,这个算法本来基于字符串,就效率和适应性来讲,都好于object的装拆箱.数据检查不是问题.春节到了,将和csdn上的弟兄们分别一段日子了,祝大家春节好!
微软那个就是object拆箱的,还多了很多检查,最后才转decimal开始计算,大概为了兼容多种类型的那个格式化接口的需要。