using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
public class MathFunction : MonoBehaviour
{
private void Start()
{
//key 范围 0-99 表示 0% 到 99%
Dictionary<int,uint> m = new Dictionary<int, uint>();
for (int i = 0; i < 100; i++)
{
m[i] = 0;
}
//f(x)为正态函数在[0,x]区间的积分
//y = f(x)函数的逆函数 x = f(y)
//x 精确到 0.0000 到 0.4999 (正态函数在零到正无穷积分值为0.5000)
//y 在 x = 0.4999 时 最大 y = 3.71905 指定 MAX_F 为 3.8
float MAX_F = 3.8f;
for (int i = 0;i < 1000000; i++)
{
int num = UnityEngine.Random.Range(0,5000);
float numR = num / 10000f;
float posf = MyErfinv(numR * 2f) * Mathf.Sqrt(2f);
int pos = (int)(posf / MAX_F * 100f);
if (pos >= 100){pos = 99;}
if (pos < 0){pos = 0;}
m[pos]++;
}
string str = "";
for(int i = 0;i < m.Count ; i++)
{
str += "百分之"+i.ToString()+" "+m[i].ToString()+" \n";
}
Debug.Log(str);
}
// 修正的逆误差函数
private float MyErfinv(float a)
{
float p, r, t;
t = MyFma(a, -a, 1.0f);
t = MyLog(t);
if (Mathf.Abs(t) > 6.125f)
{
p = 3.03697567e-10f;
p = MyFma(p, t, 2.93243101e-8f);
p = MyFma(p, t, 1.22150334e-6f);
p = MyFma(p, t, 2.84108955e-5f);
p = MyFma(p, t, 3.93552968e-4f);
p = MyFma(p, t, 3.02698812e-3f);
p = MyFma(p, t, 4.83185798e-3f);
p = MyFma(p, t, -2.64646143e-1f);
p = MyFma(p, t, 8.40016484e-1f);
}
else
{
p = 5.43877832e-9f;
p = MyFma(p, t, 1.43285448e-7f);
p = MyFma(p, t, 1.22774793e-6f);
p = MyFma(p, t, 1.12963626e-7f);
p = MyFma(p, t, -5.61530760e-5f);
p = MyFma(p, t, -1.47697632e-4f);
p = MyFma(p, t, 2.31468678e-3f);
p = MyFma(p, t, 1.15392581e-2f);
p = MyFma(p, t, -2.32015476e-1f);
p = MyFma(p, t, 8.86226892e-1f);
}
r = a * p;
return r;
}
private float MyFma(float x, float y, float z)
{
return x * y + z;
}
private float MyLog(float a)
{
float i, m, r, s, t;
int e = 0;
m = Frexpf(a, ref e);
if (m < 0.666666667f)
{
m += m;
e -= 1;
}
i = e;
m -= 1.0f;
s = m * m;
r = -0.130310059f;
t = 0.140869141f;
r = MyFma(r, s, -0.121484190f);
t = MyFma(t, s, 0.139814854f);
r = MyFma(r, s, -0.166846052f);
t = MyFma(t, s, 0.200120345f);
r = MyFma(r, s, -0.249996200f);
r = MyFma(t, m, r);
r = MyFma(r, m, 0.333331972f);
r = MyFma(r, m, -0.500000000f);
r = MyFma(r, s, m);
r = MyFma(i, 0.693147182f, r);
return r;
}
private float Frexpf(float x, ref int exp)
{
exp = 0;
if (x == 0f) return 0f;
float abs_x = Mathf.Abs(x);
if (abs_x == float.PositiveInfinity || float.IsNaN(abs_x)){
return x;
}
exp = (int)Mathf.Floor(Mathf.Log(abs_x, 2)) + 1;
float significand = x * Mathf.Pow(2, -exp);
if (Mathf.Abs(significand) >= 1f)
{
significand *= 0.5f;
exp++;
}
else if (Mathf.Abs(significand) < 0.5f && significand != 0f)
{
significand *= 2f;
exp--;
}
return significand;
}
}
//随机生成 1000000 条数据
//以下单位(条)
百分之0 30440
百分之1 30281
百分之2 30270
百分之3 30300
百分之4 29800
百分之5 29556
百分之6 29309
百分之7 28959
百分之8 28904
百分之9 28092
百分之10 28140
百分之11 27562
百分之12 27298
百分之13 26807
百分之14 26273
百分之15 25309
百分之16 24687
百分之17 24489
百分之18 23420
百分之19 23120
百分之20 22205
百分之21 21822
百分之22 20976
百分之23 20383
百分之24 19481
百分之25 19044
百分之26 18296
百分之27 17704
百分之28 16825
百分之29 16214
百分之30 15624
百分之31 14886
百分之32 13952
百分之33 13736
百分之34 12764
百分之35 12318
百分之36 11692
百分之37 10826
百分之38 10348
百分之39 9772
百分之40 9130
百分之41 8825
百分之42 8235
百分之43 7780
百分之44 7179
百分之45 6810
百分之46 6398
百分之47 5949
百分之48 5318
百分之49 5198
百分之50 4671
百分之51 4626
百分之52 4023
百分之53 3883
百分之54 3351
百分之55 3414
百分之56 3003
百分之57 2794
百分之58 2637
百分之59 2211
百分之60 2303
百分之61 2023
百分之62 1715
百分之63 1627
百分之64 1640
百分之65 1367
百分之66 1166
百分之67 1215
百分之68 1008
百分之69 762
百分之70 996
百分之71 635
百分之72 822
百分之73 608
百分之74 583
百分之75 397
百分之76 407
百分之77 391
百分之78 386
百分之79 405
百分之80 192
百分之81 209
百分之82 226
百分之83 205
百分之84 210
百分之85 201
百分之86 206
百分之87 0
百分之88 184
百分之89 0
百分之90 207
百分之91 0
百分之92 0
百分之93 194
百分之94 0
百分之95 0
百分之96 0
百分之97 191
百分之98 0
百分之99 0
文章借鉴&引用:
Inverse Error Function in C - Stack Overflow
关于C#:精确计算比例互补误差函数erfcx() | 码农家园