Files
zszq-trs/Framework/YLErp.Core/Helpers/NumberHelper.cs
T
2024-05-09 14:06:26 +08:00

524 lines
18 KiB
C#

using System.Runtime.CompilerServices;
using YLErp.Commons;
namespace System
{
/// <summary>
/// 数字帮助类
/// </summary>
public static class NumberHelper
{
/// <summary>
/// 非四舍五入情况下截取最大小数位数字
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Truncate(double value, int minDecimals, int maxDecimals, bool percent)
{
var decimals = maxDecimals > minDecimals ? maxDecimals : minDecimals;
if (percent)
{
decimals += 2;
}
if (decimals > 0)
{
var pow = Math.Pow(10, decimals);
return Math.Truncate(value * pow) / pow;
}
else
{
return Math.Truncate(value);
}
}
public static decimal Truncate(decimal value, int minDecimals, int maxDecimals, bool percent)
{
var decimals = maxDecimals > minDecimals ? maxDecimals : minDecimals;
if (percent)
{
decimals += 2;
}
if (decimals > 0)
{
var pow = Math.Pow(10, decimals);
var dePow = Convert.ToDecimal(pow);
return Math.Truncate(value * dePow) / dePow;
}
else
{
return Math.Truncate(value);
}
}
/// <summary>
/// 获取数字格式化字符串
/// </summary>
/// <param name="minDecimals">最小小数位</param>
/// <param name="maxDecimals">最大小数位</param>
/// <param name="percent">是否百分比格式</param>
/// <param name="grouping">是否千分位分组</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetFormat(int minDecimals, int maxDecimals, bool percent, bool grouping)
{
var sb = StringBuilderPool.Acquire();
sb.Append(grouping ? "#,##0" : "0");
if (minDecimals > 0)
{
sb.Append('.').Append('0', minDecimals);
if (maxDecimals > minDecimals)
{
sb.Append('#', maxDecimals - minDecimals);
}
}
else if (maxDecimals > 0)
{
sb.Append('.').Append('#', maxDecimals);
}
if (percent)
{
sb.Append('%');
}
return sb.Release();
}
/// <summary>
/// 转换为中文数字
/// </summary>
/// <param name="number">数字</param>
/// <param name="moneyStyle">金钱样式</param>
public static string ConvertToChinese(double number, bool moneyStyle)
{
return moneyStyle ? ChineseNumberConvert.MoneyCn(number) : ChineseNumberConvert.NumberCn(number);
}
/// <summary>
/// 转换为人民币大写
/// </summary>
public static string CmycurD(double num)
{
return ChineseNumberConvert.CmycurD(num);
}
/// <summary>
/// 小写转大写数字(整数)
/// </summary>
public static string CurrToChnInt(int n)
{
return ChineseNumberConvert.CurrToChnInt(n);
}
/// <summary>
/// 正常化double值(NAN或无限大数字转换为0)
/// </summary>
public static double Normalize(this double value)
{
return double.IsNaN(value) || double.IsInfinity(value) ? 0 : value;
}
/// <summary>
/// 正常化double值(NAN或无限大数字转换为0)
/// </summary>
public static double Normalize(this double? value)
{
return !value.HasValue || double.IsNaN(value.Value) || double.IsInfinity(value.Value) ? 0 : value.Value;
}
/// <summary>
/// 检查double值是否为(NAN或无限大数字)
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool IsNormalize(this double value)
{
return !(double.IsNaN(value) || double.IsInfinity(value));
}
/// <summary>
/// 检查double值是否为(NULL NAN或无限大数字)
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool IsNormalize(this double? value)
{
return value.HasValue && value.Value.IsNormalize();
}
/// <summary>
/// 浮点数格式化
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Format(double? d, string fmt)
{
return d.HasValue ? d.Value.ToString(fmt) : "";
}
/// <summary>
/// 字符串转换为doulbe数字
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDouble(string str, double defaultValue = 0)
{
return double.TryParse(str, out var val) ? val : defaultValue;
}
/// <summary>
/// decimal?转换为doulbe数字
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDouble(this decimal? d, double defaultValue = 0)
{
return d.HasValue ? Convert.ToDouble(d) : defaultValue;
}
/// <summary>
/// double转换为decimal(未处理double参数是否超出了decimal.MaxValue|MinValue的范围)
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal ToDecimal(this double d, decimal defaultValue = 0)
{
return double.IsNaN(d) || double.IsInfinity(d) ? defaultValue : new decimal(d);
}
/// <summary>
/// 尝试解析百分比数字(根据传入的字符层末尾是否为%判断)
/// </summary>
public static bool TryParse(string str, out double dvalue, out bool isPercent)
{
dvalue = 0;
isPercent = false;
if (string.IsNullOrWhiteSpace(str))
{
return false;
}
isPercent = str.EndsWith("%");
if (isPercent)
{
str = str.TrimEnd('%');
}
if (double.TryParse(str, out dvalue))
{
if (isPercent)
{
dvalue /= 100;
}
return true;
}
return false;
}
/// <summary>
/// doulbe取绝对值()
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Abs(double value)
{
return double.IsNaN(value) || double.IsInfinity(value) ? 0 : Math.Abs(value);
}
/// <summary>
/// 中文数字转换类
/// </summary>
static class ChineseNumberConvert
{
const string cPointCn = "点十百千万十百千亿十百千";
const string cNumberCn = "零一二三四五六七八九";
public static string NumberCn(string number)
{
var S = number.ToString();
if (S == "0")
{
return "" + cPointCn[0];
}
if (!S.Contains("."))
{
S += ".";
}
var P = S.IndexOf(".");
var Result = "";
for (var i = 0; i < S.Length; i++)
{
if (P == i)
{
Result = Result.Replace("零十零", "零");
Result = Result.Replace("零百零", "零");
Result = Result.Replace("零千零", "零");
Result = Result.Replace("零十", "零");
Result = Result.Replace("零百", "零");
Result = Result.Replace("零千", "零");
Result = Result.Replace("零万", "万");
Result = Result.Replace("零亿", "亿");
Result = Result.Replace("亿万", "亿");
Result = Result.Replace("零点", "点");
}
else
{
try
{
if (P > i)
{
Result += "" + cNumberCn[S[i] - '0'] + cPointCn[P - i - 1];
}
else
{
Result += "" + cNumberCn[S[i] - '0'];
}
}
catch
{
return "";
}
}
}
if (Result.Substring(Result.Length - 1, 1) == "" + cPointCn[0])
{
Result = Result.Remove(Result.Length - 1); // 一点-> 一
}
if (Result[0] == cPointCn[0])
{
Result = cNumberCn[0] + Result; // 点三-> 零点三
}
if ((Result.Length > 1) && (Result[1] == cPointCn[1]) &&
(Result[0] == cNumberCn[1]))
{
Result = Result.Remove(0, 1); // 一十三-> 十三
}
return Result;
}
public static string NumberCn(double number)
{
return NumberCn(number.ToString());
}
/// <summary>
/// 2021年7月20日微调
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string MoneyCn(double number)
{
if (number == 0)
{
return "零";
}
/*
* 修改原因是因为142,547.580 使用Math.Truncate(number * 100)后
* 变为142,547.570
*/
var Result = NumberCn(Math.Truncate(number * 100 + 1e-6) / 100);
Result = Result.Replace("一", "壹");
Result = Result.Replace("二", "贰");
Result = Result.Replace("三", "叁");
Result = Result.Replace("四", "肆");
Result = Result.Replace("五", "伍");
Result = Result.Replace("六", "陆");
Result = Result.Replace("七", "柒");
Result = Result.Replace("八", "捌");
Result = Result.Replace("九", "玖");
Result = Result.Replace("九", "玖");
Result = Result.Replace("十", "拾");
Result = Result.Replace("百", "佰");
Result = Result.Replace("千", "仟");
if (Result.Contains("点"))
{
var P = Result.IndexOf("点");
if (Result.Length >= P + 3)
{
Result = Result.Insert(P + 3, "分");
}
Result = Result.Insert(P + 2, "角");
Result = Result.Replace("点", "圆");
Result = Result.Replace("角分", "角");
Result = Result.Replace("零分", "");
Result = Result.Replace("零角", "");
Result = Result.Replace("分角", "");
if (Result.Substring(0, 2) == "零圆")
{
Result = Result.Replace("零圆", "");
}
}
else
{
Result += "圆整";
}
Result = "人民币" + Result;
return Result;
}
/// <summary>
/// 转换为人民币大写
/// </summary>
public static string CmycurD(double num)
{
var str1 = "零壹贰叁肆伍陆柒捌玖"; //0-9所对应的汉字
var str2 = "万仟佰拾亿仟佰拾万仟佰拾元角分"; //数字位所对应的汉字
var str3 = ""; //从原num值中取出的值
var str4 = ""; //数字的字符串形式
var str5 = ""; //人民币大写金额形式
int i; //循环变量
int j; //num的值乘以100的字符串长度
var ch1 = ""; //数字的汉语读法
var ch2 = ""; //数字位的汉字读法
var nzero = 0; //用来计算连续的零值是几个
int temp; //从原num值中取出的值
num = double.Parse(num.ToString("0.##")); //将num取绝对值并四舍五入取2位小数
str4 = Math.Round(num * 100).ToString("F0"); //将num乘100并转换成字符串形式
j = str4.Length; //找出最高位
if (j > 15) { return "溢出"; }
str2 = str2.Substring(15 - j); //取出对应位数的str2的值。如:200.55,j为5所以str2=佰拾元角分
//循环取出每一位需要转换的值
for (i = 0; i < j; i++)
{
str3 = str4.Substring(i, 1); //取出需转换的某一位的值
temp = Convert.ToInt32(str3); //转换为数字
if (i != (j - 3) && i != (j - 7) && i != (j - 11) && i != (j - 15))
{
//当所取位数不为元、万、亿、万亿上的数字时
if (str3 == "0")
{
ch1 = "";
ch2 = "";
nzero += 1;
}
else
{
if (str3 != "0" && nzero != 0)
{
ch1 = "零" + str1.Substring(temp * 1, 1);
ch2 = str2.Substring(i, 1);
nzero = 0;
}
else
{
ch1 = str1.Substring(temp * 1, 1);
ch2 = str2.Substring(i, 1);
nzero = 0;
}
}
}
else
{
//该位是万亿,亿,万,元位等关键位
if (str3 != "0" && nzero != 0)
{
ch1 = "零" + str1.Substring(temp * 1, 1);
ch2 = str2.Substring(i, 1);
nzero = 0;
}
else
{
if (str3 != "0" && nzero == 0)
{
ch1 = str1.Substring(temp * 1, 1);
ch2 = str2.Substring(i, 1);
nzero = 0;
}
else
{
if (str3 == "0" && nzero >= 3)
{
ch1 = "";
ch2 = "";
nzero += 1;
}
else
{
//if (j > 11)
//{
// ch1 = "";
// nzero += 1;
//}
//else
//{
ch1 = "";
ch2 = str2.Substring(i, 1);
nzero += 1;
//}
}
}
}
}
if (i == (j - 11) || i == (j - 3))
{
//如果该位是亿位或元位,则必须写上
ch2 = str2.Substring(i, 1);
}
str5 = str5 + ch1 + ch2;
if (i == j - 1 && str3 == "0")
{
//最后一位(分)为0时,加上“整”
str5 += '整';
}
}
if (num == 0)
{
str5 = "零元整";
}
return str5;
}
/// <summary>
/// 小写转大写数字(整数)
/// 这个从otcformathelper迁移过来,最好也调用NumberCn
/// </summary>
public static string CurrToChnInt(int n)
{
string[] c_Num1 = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
string[] c_fh = { "", "十", "百", "千", "万" };
string s = n.ToString();
string ss = "";
int j = s.Length - 1;
for (int i = 0; i <= j; i++)
{
int num = Convert.ToInt32(s.Substring(i, 1));
if (j == i)
{
if (j == 0 || num != 0)
{
ss += c_Num1[num];
}
}
else
{
if (num == 1)
{
ss += c_fh[j - i];
}
else
{
ss += c_Num1[num] + c_fh[j - i];
}
}
}
return ss;
}
}
}
}