You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.9 KiB
C#

5 months ago
using System.Text;
namespace DS.WMS.Core.Application.Dtos
{
/// <summary>
/// 可将指定金额的数字转换为人民币大写
/// </summary>
public sealed class Money
{
const string Yuan = "元"; // “元”,可以改为“圆”、“卢布”之类
const string Jiao = "角"; // “角”,可以改为“拾”
const string Fen = "分"; // “分”,可以改为“美分”之类
const string Digit = "零壹贰叁肆伍陆柒捌玖"; // 大写数字
bool isAllZero = true; // 片段内是否全零
bool isPreZero = true; // 低一位数字是否是零
bool Overflow = false; // 溢出标志
long money100; // 金额*100即以“分”为单位的金额
long value; // money100的绝对值
StringBuilder sb = new StringBuilder(); // 大写金额字符串,逆序
// 只读属性: "零元"
readonly string[] Unit = [Yuan, "万", "亿", "万", "亿亿"];
public string ZeroString { get { return Digit[0] + Yuan; } }
/// <summary>
/// 初始化
/// </summary>
/// <param name="value"></param>
public Money(double value) : this(Convert.ToDecimal(value))
{
}
5 months ago
/// <summary>
/// 初始化
/// </summary>
/// <param name="value"></param>
public Money(decimal value)
{
try { money100 = (long)(value * 100m); }
catch { Overflow = true; }
if (money100 == long.MinValue)
Overflow = true;
5 months ago
}
/// <summary>
/// 返回汉字大写金额
5 months ago
/// </summary>
/// <returns>大写金额字符串</returns>
/// <exception cref="OverflowException">金额超出范围</exception>
5 months ago
public override string ToString()
{
if (Overflow) throw new OverflowException("金额超出范围");
5 months ago
if (money100 == 0) return ZeroString;
value = Math.Abs(money100);
5 months ago
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("负");
var str = Reverse();
if (money100 % 100 == 0)
str += "整";
return str;
5 months ago
}
// 解析“片段”: “角分(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();
}
}
}
5 months ago