using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
namespace Apewer
{
/// 数值实用工具。
public static class NumberUtility
{
#region 随机数。
/// 用于生成随机数的时钟位置。
private static int RandomSeed = 327680;
private static void RandomInit()
{
var now = DateTime.Now;
var timer = (float)((double)(checked((60 * now.Hour + now.Minute) * 60 + now.Second)) + (double)now.Millisecond / 1000.0);
int num1 = RandomSeed;
int num2 = BitConverter.ToInt32(BitConverter.GetBytes(timer), 0);
num2 = ((num2 & 65535) ^ num2 >> 16) << 8;
num1 = (num1 & -16776961) | num2;
RandomSeed = num1;
}
/// 生成不大于 1 的随机数,最小为 0。
public static float Random(float max = 1F)
{
RandomInit();
int num1 = RandomSeed;
if ((double)max != 0.0)
{
if ((double)max < 0.0)
{
num1 = BitConverter.ToInt32(BitConverter.GetBytes(max), 0);
long vnum2 = (long)num1;
vnum2 &= unchecked((long)((ulong)-1));
num1 = checked((int)(vnum2 + (vnum2 >> 24) & 16777215L));
}
num1 = checked((int)(unchecked((long)num1) * 1140671485L + 12820163L & 16777215L));
}
RandomSeed = num1;
return (float)num1 / 16777216f;
}
/// 生成随机整数,包含最小值和最大值。
/// 最小值。
/// 最大值。
///
public static int Random(int max, int min = 0)
{
if (max == min) return max;
if (max < min)
{
var temp = max;
max = min;
min = temp;
}
var rate = (max - min + 1) * Random();
var result = min + (int)rate;
return result;
}
#endregion
#region Restrict 约束值范围。
/// 约束值范围,若源值不在范围中,则修改为接近的值。
public static T Restrict(T origin, T min, T max) where T : IComparable
{
try
{
// 检查条件 min > max : 返回原始值。
var condition = min.CompareTo(max);
if (condition > 0) return origin;
if (origin.CompareTo(min) < 0) return min;
if (origin.CompareTo(max) > 0) return max;
return origin;
}
catch { }
return origin;
}
#endregion
/// 平均值。
public static double Average(params double[] values)
{
var amount = 0d;
foreach (var i in values) amount += i;
return amount / Convert.ToDouble(values.Length);
}
#region 最小值、最大值。
private static T GetMost(Func replace, T[] values)
{
if (values == null) return default;
var length = values.LongLength;
if (length == 0L) return default;
if (length == 1L) return values[0L];
var most = values[0];
for (var i = 1L; i < length; i++)
{
var value = values[i];
if (value == null) continue;
if (most == null)
{
most = value;
}
else
{
var doReplace = replace(most, value);
if (doReplace) most = value;
}
}
return most;
}
// 无法输出正确结果。
// public static T GetMin(params IComparable[] values)
// {
// var result = GetMost((a, b) => a.CompareTo(b) == 1, values);
// return result == null ? default : (T)result;
// }
// 无法输出正确结果。
// public static T GetMin(params IComparable[] values)
// {
// var result = GetMost((a, b) => a.CompareTo((T)b) == 1, values);
// return result == null ? default : (T)result;
// }
// 无法输出正确结果。
// public static T GetMax(params IComparable[] values)
// {
// var result = GetMost((a, b) => a.CompareTo(b) == -1, values);
// return result == null ? default : (T)result;
// }
// 无法输出正确结果。
// public static T GetMax(params IComparable[] values)
// {
// var result = GetMost((a, b) => a.CompareTo((T)b) == -1, values);
// return result == null ? default : (T)result;
// }
/// 最小值。
public static byte Min(params byte[] values) => GetMost((a, b) => a > b, values);
/// 最小值。
public static int Min(params int[] values) => GetMost((a, b) => a > b, values);
/// 最小值。
public static long Min(params long[] values) => GetMost((a, b) => a > b, values);
/// 最小值。
public static float Min(params float[] values) => GetMost((a, b) => a > b, values);
/// 最小值。
public static double Min(params double[] values) => GetMost((a, b) => a > b, values);
/// 最小值。
public static decimal Min(params decimal[] values) => GetMost((a, b) => a > b, values);
/// 最大值。
public static byte Max(params byte[] values) => GetMost((a, b) => a < b, values);
/// 最大值。
public static int Max(params int[] values) => GetMost((a, b) => a < b, values);
/// 最大值。
public static long Max(params long[] values) => GetMost((a, b) => a < b, values);
/// 最大值。
public static float Max(params float[] values) => GetMost((a, b) => a < b, values);
/// 最大值。
public static double Max(params double[] values) => GetMost((a, b) => a < b, values);
/// 最大值。
public static decimal Max(params decimal[] values) => GetMost((a, b) => a < b, values);
#endregion
/// Pearson Correlation Coefficient 皮尔逊相关系数。计算两个数组的相似度。数组长度不相等时,以 0 填充不足的长度。
///
/// 0.8 ~ 1.0 : 极强相关
/// 0.6 ~ 0.8 : 强相关
/// 0.4 ~ 0.6 : 中等程度相关
/// 0.2 ~ 0.4 : 弱相关
/// 0.0 ~ 0.2 : 极弱相关或无相关
///
///
public static double Pearson(double[] bytes1, double[] bytes2)
{
var length1 = bytes1 == null ? 0L : bytes1.LongLength;
var length2 = bytes2 == null ? 0L : bytes2.LongLength;
var length = Math.Max(length1, length2);
if (length < 1) return 1D;
var x = new double[length];
var y = new double[length];
for (var i = 0L; i < length; i++)
{
if (i < length1) x[i] = bytes1[i];
if (i < length2) y[i] = bytes2[i];
}
int n = x.Length; // 数组长度。
double s = 0d; // 分子。
double m1 = 0d, m2 = 0d; // 分母。
double xa = Average(x);
double ya = Average(y);
for (int i = 0; i < n; i++)
{
s += (x[i] - xa) * (y[i] - ya);
m1 += Math.Pow(x[i] - xa, 2);
m2 += Math.Pow(y[i] - ya, 2);
}
double r = s / (Math.Sqrt(m1) * Math.Sqrt(m2));
return r;
}
#region 从 String 转为数值。
// 修剪数值字符串。
private static string Trim(string text)
{
if (string.IsNullOrEmpty(text)) return null;
const string allowed = "0123456789.%+-Ee。";
var input = text.Length;
var output = 0;
var chars = new char[input];
for (var i = 0; i < text.Length; i++)
{
var c = text[i];
if (c == '。') c = '.';
else if (allowed.IndexOf(c) < 0) continue;
chars[output] = c;
output += 1;
}
if (output == input) return text;
if (output < 1) return null;
return new string(chars, 0, output);
}
private static T GetNumber(object @object, Func convert, Func percent = null)
{
if (@object == null) return default(T);
if (@object is T) return (T)@object;
var text = (@object is string) ? (string)@object : "";
var trim = Trim(text);
if (trim == null) return default;
// 获取百分号的个数。
var pow = 0;
while (trim.Length > 0 && trim.EndsWith("%"))
{
trim = trim.Substring(0, trim.Length - 1);
pow += 1;
}
if (trim.Length < 1) return default;
// 转换。
try
{
var value = convert(trim);
if (pow > 0 && percent != null)
{
var denominator = Math.Pow(100, pow);
value = percent(value, denominator);
}
return value;
}
catch { return default; }
}
private static decimal DecimalAsFloat(string text)
{
try { return Convert.ToDecimal(text); } catch { }
try { return decimal.Parse(text, NumberStyles.Float); } catch { }
return default(decimal);
}
/// 获取布尔对象。
public static bool Boolean(object any)
{
if (any.IsNull()) return false;
if (any is bool _bool) return _bool;
if (any is byte _byte) return _byte == 1;
if (any is sbyte _sbyte) return _sbyte == 1;
if (any is short _short) return _short == 1;
if (any is ushort _ushort) return _ushort == 1;
if (any is int _int) return _int == 1;
if (any is uint _uint) return _uint == 1;
if (any is long _long) return _long == 1;
if (any is ulong _ulong) return _ulong == 1;
if (any is float _float) return _float == 1;
if (any is double _double) return _double == 1;
if (any is decimal _decimal) return _decimal == 1;
if (any is string _string)
{
var lower = TextUtility.Lower(_string);
if (lower == "true" || lower == "yes" || lower == "y" || lower == "1") return true;
}
return false;
}
/// 获取单精度浮点对象。
public static float Float(object number) => GetNumber(number, Convert.ToSingle, (v, d) => v / Convert.ToSingle(d));
/// 获取单精度浮点对象。
public static float Single(object number) => GetNumber(number, Convert.ToSingle, (v, d) => v / Convert.ToSingle(d));
/// 获取双精度浮点对象。
public static double Double(object number) => GetNumber(number, Convert.ToDouble, (v, d) => v / d);
/// 获取 Decimal 对象。
public static decimal Decimal(object number) => GetNumber(number, DecimalAsFloat, (v, d) => v / Convert.ToDecimal(d));
/// 获取 Byte 对象。
public static byte Byte(object number) => GetNumber(number, Convert.ToByte);
/// 获取 SByte 对象。
public static sbyte SByte(object number) => GetNumber(number, Convert.ToSByte);
/// 获取 Int16 对象。
public static short Int16(object number) => GetNumber(number, Convert.ToInt16);
/// 获取 UInt16 对象。
public static ushort UInt16(object number) => GetNumber(number, Convert.ToUInt16);
/// 获取 Int32 对象。
public static int Int32(object number) => GetNumber(number, Convert.ToInt32);
/// 获取 UInt32 对象。
public static uint UInt32(object number) => GetNumber(number, Convert.ToUInt32);
/// 获取 Int64 对象。
public static long Int64(object number) => GetNumber(number, Convert.ToInt64);
/// 获取 UInt64 对象。
public static ulong UInt64(object number) => GetNumber(number, Convert.ToUInt64);
#endregion
}
}