美文网首页
Unity 放置类大数据

Unity 放置类大数据

作者: 忆中异 | 来源:发表于2021-05-06 15:26 被阅读0次

    目前常用的数据类型

    sbyte八位有符号整数 -128~127
    byte八位无符号整数 0~255
    short十六位无符号整数 0~65535

    • int三十二位有符号整数 -214783648~214783647
      unit三十二位无符号整数 0~4294967295
    • long六十四位有符号整数 -9223372036854775808~9223372036854775807
      ulong六十四为无符号整数 0~18446744073709551615
      char十六位字符类型 所有Unicode编码字符
    • float三十二单精度浮点类型 大约七个有效十进制数位
    • double六十四位双精度浮点类型 大约15~16个有效十进制数
      decimal一百二十八位高精度十进制数类型 大约28~29有效十进制数位

    在项目中大家可能比较常用的是int long float double

    下图是在unity打印的结果,各个数据类型所占字节数以及最大、最小值


    image.png
    • float和int类型同样是占有32位,为什么float能存储3.402823E+38
      机器不会骗人,原因就是它不是按int这么存数据的。比如一个float 数据
      1024.1024 等价于 1.0241024 * 10^3 (3表示指数,1.0241024表示有效数字)float其实只是把符号、指数、有效数字3部分保存,真正在运算的时候是根据指数在移位操作。
      float把 32位分成了3部分,1位(符号位)8位(指数位)23位(有效数字)那么 1+ 8 + 23 等于32吧,所以float的32位是这么来的。23位有效数字就表示float真正能存的精度,23位小数部分是反被储存的部分,所以它是有24位存储的,2^24(2的24次方)=16777216,下面做个试验
            float a = 1658459f;
            float b = a + 0.1f;
            Debug.Log($"a={a},b={b}");
    

    定义a=1658459f,b=a+0.1f,想想a、b最终输出结果是多少呢?


    image.png

    这是什么原因呢?这是因为浮点数超过七位数(包括小数位),计算精度会降低,将会出现上面的结果;那是否意味着a=b呢?答案是NO,只能是近似相等。

    float我们介绍完了,double的原理和float差不多,double占8字节,1位符号位+11位指数+52位有效数字 = 64位。double的有效2^53(2的53次方)=9007199254740992,超过9007199254740992.xxx那么很抱歉它们的结果是一致的。

    而且浮点数计算结果不同的CPU计算出来可能是不一致的,像帧同步那种游戏基本应该告别float和double了。例如iphone对浮点型计算就比较弱。

    最后我们在聊一下定点数,应对解决精度问题,c#提供了定点数decimal关键字。可以看到它是由16个字节组成也就是128位,内存大小相当于4个float或者2个double 取值范围也很高。
    1-12字节:它先用前12个字节来表示定点数数据,1字节8位,12个字节就是8*12 =96位,那么它的取值范围就是2^96(2的96次方)7.922816251426E+28
    13-15字节:在用3个字节来表示指数
    16字节:最后一个字节来表示符号
    只要数据在10进制28-29位之间,小数点在中间任意位置均可。数据运算就不会像float和double一样被和谐了。所以说如果需要准确精度的小数计算就一定要使用定点数。

    double(双精度浮点)类型最大值为1.79769313486232E+308,我们一下主要用double于咱们自己定义数据类型做比较。

    放置类几种常用数值比较

    一般做放置类型游戏,数据是比较大的,你永远不知道策划大佬的数值有多大,我们怎么能满足策划大佬的需求呢?double可能在大多数情况下能满足策划大佬需求,虽然有的策划说我的数值表里面数值不会超过double的最大值,但谁能保证玩家的金钱不会越界呢?希望大家都能把玩家基数想的足够大,几百万,上千万甚至过亿,梦想总是要有的,万一实现了呢,大家的小目标还会远吗?嘿嘿

    我想阅读到这里就会有同学提出BigInteger超大整型数字
    BigInteger
    自.net framework 4.0开始引入, 位于命名空间:

    namespace System.Numerics
    

    设计用于存储超大整型数字,所以只要内存够大,存储是没有上限和下限的,否则如果数字过大的话,会遇到OutOfMemory的异常。


    image.png

    下面看看BigInteger的运算
    加:bi1.add(bi2)
    减:bi1.subtract(bi2)
    乘:bi1.multiply(bi2)
    除: bi1.divide(bi2)
    取余:bi1.remainder(bi2)
    是不是和我们常用的值类型加、减、乘、除不太一样
    我们再回头看看BigInteger的定义超大整型数字整型划重点,一会要考。
    如果咱们用整型,策划大佬会答应吗?能满足小数的需求么?一毛钱不是钱么,日积月累定能超过一块钱。
    Q:那如果说前期用double类型后期再把double类型换成BigInteger类型,反正double类型超过7位数计算精度也不准确,判断超过7位数就转成BigInteger,此时小数点后面数字相对于百万几乎可以忽略不计(放置类数值精度也没要求那么准确)
    A:我只想说累不?用两种类型转换;那如果A=1E+8用BigInteger类型存储,B=1E+6用double类型存储,A和B的加、减、乘、除,我们又当如何计算呢?

    Double最大值为1.79769313486232E+308,基本上能满足策划大佬的数据要求,但作为开发人员做技术要严谨,为了能满足大数据需求,防止广大用户数据越界,我自定义一个数据类型Long2,下面讲下这个数据类型的设计思路。

    自定义大数据类型

    设计思路基于科学计算法
    定于两个变量,float类型变量x作为计数,long类型变量y作为10的指数(单位),x数值最大不超过8位正数;

    1.假设有个数值A=124534563812347524204534转换成Long2类型,先求出y,y=INT(LOG(A)-7)=16;x=A/(10^y)=12453456.381(保留三位小数);最终我们计算出long1=12453456.381,16
    2.另一个数值B=78541124634534535247454转换成Long2类型,按第一步先求出y=INT(LOG(B)-7)=15;x=B/(10^y)=78541124.635(保留三位小数);最终我们计算出long2 = 78541124.635,15
    下面计算A、B的加减乘除
    A+B 、A-B

    • 带有指数数字的相加或者相减要保持指数一样
      咱们转换下,long1=12453456.381,16 long2=7854112.463,16
      加法最终结果为:20307568.844,16
      减法最终结果为:4599343.918,16
      AxB
      long1计数x1乘以long2计数x2,计数想成结果为x=x1x2=9.781E+14,发现是大于八位数的,此时我们需要对计数想成结果做次单位转换计算出多余位数moreY = INT(LOG10(x)-7); x=x/(10^moreY)=97810843;最终的y应该等于long1的y1加long2*的y2加多余位数,y=y1+y2+moreY = 38;最终结果为97810843,38
      A/B
      x=x1/x2=0.15855969,计算出多余位数moreY = INT(LOG10(x)-7) = -8;x= x/(10^moreY) = 15855968;y = y1-y2+moreY = -7;最终结果为15855968,-7

    备注:目前没看到内存修改器可以修改此类型数据

    下面贴出c#和lua代码

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine; 
    
    namespace Foundation
    {
        public struct Long2 : System.IEquatable<Long2>
        {
            public float x;
            public long y;     
            public bool Equals(Long2 other)
            {
                return x == other.x && y == other.y;
            }
            public override bool Equals(System.Object obj)
            {
                if (obj == null) return false;
    
                var rhs = (Long2)obj;
    
                return x == rhs.x &&
                       y == rhs.y;
            }
            public override int GetHashCode()
            {
                return (int)((int)x * 73856093 ^ y * 19349663);
            }
            public static Long2 zero { get { return new Long2(); } }
            public static Long2 one { get { return new Long2(1,0); } }
            //public Long2() { }
            public Long2(Long2 lhr)
            {
                this.x = lhr.x;
                this.y = lhr.y;
            }
            public Long2(int _x)
            {
                if(_x ==0)
                {
                    x = y = 0;
                }
                else
                {
                    y = (long)Math.Round(Math.Log10(Math.Abs(_x)) - 7); //最大单位
                    x = (float)(_x / Math.Pow(10, y));
                    Convert(ref x,ref y);
                }
                
            }
            public Long2(long _x)
            {
                if(_x == 0)
                {
                    x = y = 0;
                }
                else
                {
                    y = (long)Math.Round(Math.Log10(Math.Abs(_x)) - 7); //最大单位
                    x = (float)(_x / Math.Pow(10, y));
                    Convert(ref x, ref y);
                }
                
            }
            public Long2(float _x)
            {
                if(_x ==0)
                {
                    x = y = 0;
                }
                else
                {
                    y = (long)Math.Round(Math.Log10(Math.Abs(_x)) - 7); //最大单位
                    x = (float)(_x / Math.Pow(10, y));
                    Convert(ref x, ref y);
                }
                
            }
            public Long2(double _x)
            {
                if(_x ==0)
                {
                    x = y = 0;
                }
                else
                {
                    y = (long)Math.Round(Math.Log10(Math.Abs(_x)) - 7); //最大单位
                    x = (float)(_x / Math.Pow(10, y));
                    Convert(ref x, ref y);
                }
               
            }
            public Long2(int _x, int _y)
            {
                x = (float)_x;
                y = _y;
                Convert(ref x, ref y);
            }
            public Long2(long _x,long _y)
            {
                x = (float)_x;
                y = _y;
                Convert(ref x, ref y);
            }
            public Long2(float _x,long _y)
            {
                x = _x;
                y = _y;
                Convert(ref x, ref y);
            }
            public Long2(string str)
            {                                     
                string[] st = str.Split(',');
                long unit = 0;
                if (st.Length > 1)
                    unit = long.Parse(st[1]);  
                try
                {
                    float s = float.Parse(st[0]);
                    if (s == 0)
                    {
                        x = 0;
                        y = 0;
                    }
                    else
                    {
                        long moreUnit = (long)Math.Round(Math.Log10(Math.Abs(s)) - 7);  //计算多余位
                        if (moreUnit < 0)
                        {
                            x = s;
                            y = unit;
                        }
                        else
                        {
                            x = (float)(s / Math.Pow(10, moreUnit));
                            y = unit + moreUnit;
                        }
                        if(y < 0)
                        {
                            x = (float)(x * Math.Pow(10, y));
                            y = 0;
                        }
                    }      
                    
                }
                catch(Exception ex)
                {
                    x = y = 0;                                             
                    Debug.LogError($"long {str}溢出{ex.Message}");
                }  
                
            }
            public static bool operator ==(Long2 lhs, Long2 rhs)
            {
                if (lhs.x == 0 && rhs.x == 0)
                    return true;
                return lhs.x == rhs.x &&
                       lhs.y == rhs.y; 
            }
    
            public static bool operator !=(Long2 lhs, Long2 rhs)
            {
                return lhs.x != rhs.x ||
                       lhs.y != rhs.y; 
            }
            public static bool operator <(Long2 lhs, Long2 rhs)
            {
                Long2 l = lhs - rhs;
                if (l.x < 0) return true;
                else return false; 
                                 
            }
            public static bool operator <=(Long2 lhs, Long2 rhs)
            {
                Long2 l = lhs - rhs;
                if (l.x <= 0) return true;
                else return false;
            }
            public static bool operator >(Long2 lhs, Long2 rhs)
            {
    
                Long2 l = lhs - rhs;
                if (l.x >0) return true;
                else return false;
            }
            public static bool operator >=(Long2 lhs, Long2 rhs)
            {
                Long2 l = lhs - rhs;
                if (l.x >= 0) return true;
                else return false;
            }
            public static Long2 operator -(Long2 lhs, Long2 rhs)
            {
                long unit = Math.Max(lhs.y,rhs.y); //最大单位
                lhs.x = (float)(lhs.x * Math.Pow(10, lhs.y - unit));
                lhs.y = unit;
                rhs.x = (float)(rhs.x * Math.Pow(10, rhs.y - unit));
                rhs.y = unit;
                lhs.x = lhs.x - rhs.x;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator -(Long2 lhs)
            {
                lhs.x = -lhs.x;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator +(Long2 lhs, Long2 rhs)
            {
                long unit = Math.Max(lhs.y, rhs.y); //最大单位
                lhs.x = (float)(lhs.x * Math.Pow(10, lhs.y - unit));
                lhs.y = unit;
                rhs.x = (float)(rhs.x * Math.Pow(10, rhs.y - unit));
                rhs.y = unit;
                lhs.x = lhs.x + rhs.x;
                float a = 57894212357.5679f;
                if (lhs.x == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round(Math.Log10(Math.Abs(lhs.x)) - 7);  //计算多余位
                lhs.x = (float)(lhs.x / Math.Pow(10, moreUnit));
                lhs.y += moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator *(Long2 lhs, Long2 rhs)
            {
                lhs.x *= rhs.x;
                if (lhs.x == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round(Math.Log10(Math.Abs(lhs.x)) - 7);  //计算多余位
                lhs.x = (float)(lhs.x / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + rhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator *(Long2 lhs, int rhs)
            {
                lhs.x *= rhs;
                if (lhs.x == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(lhs.x)) - 7));  //计算多余位
                lhs.x = (float)(lhs.x / Math.Pow(10, moreUnit));
                lhs.y = lhs.y  + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator *(Long2 lhs, float rhs)
            {
                float hs = lhs.x * rhs;
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位
                lhs.x = (float)(hs / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator *(Long2 lhs, double rhs)
            {
                float hs = (float)(lhs.x * rhs);
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位
                lhs.x = (float)(hs / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator *(Long2 lhs, long rhs)
            {
                lhs.x *=  rhs;
                if (lhs.x == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round(Math.Log10(Math.Abs(lhs.x)) - 7);  //计算多余位
                lhs.x = (float)(lhs.x / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator /(Long2 lhs, Long2 rhs)
            {
                if(rhs == Long2.zero)
                {
                    Debug.LogError($"被除数为零");
                    return lhs;
                }
                float hs =  lhs.x / rhs.x;
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位   
                lhs.x = (float)(hs / Math.Pow(10, moreUnit)); 
                lhs.y = lhs.y - rhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs; 
            }
            public static Long2 operator /(Long2 lhs, long rhs)
            {
                if (rhs == 0)
                {
                    Debug.LogError($"被除数为零");
                    return lhs;
                }
                float hs = lhs.x / rhs;
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位
                lhs.x = (float)(hs / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator /(Long2 lhs, float rhs)
            {
                if (rhs == 0)
                {
                    Debug.LogError($"被除数为零");
                    return lhs;
                }
                float hs = lhs.x / rhs;
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位
                lhs.x = (float)(hs / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator /(Long2 lhs, double rhs)
            {
                if (rhs == 0)
                {
                    Debug.LogError($"被除数为零");
                    return lhs;
                }
                float hs = (float)(lhs.x / rhs);
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位
                lhs.x = (float)(hs / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public static Long2 operator /(Long2 lhs, int rhs)
            {
                if (rhs == 0)
                {
                    Debug.LogError($"被除数为零");
                    return lhs;
                }
                float hs = lhs.x / rhs;
                if (hs == 0)
                    return Long2.zero;
                long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //计算多余位
                lhs.x = (float)(hs / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                lhs = Convert(lhs);
                return lhs;
            }
            public object this[int i]
            {
                get
                {
                    return i == 0 ? x : y;
                }
                set
                {
                    if (i == 0) x = (float)value;
                    else y = (long)value;   
                }
            }
            public static Long2 Convert(Long2 lhs)
            {
                long moreUnit = -7;
                if (lhs.x !=0)
                    moreUnit = (long)Math.Round((Math.Log10(Math.Abs(lhs.x)) - 7));  //计算多余位
                lhs.x = (float)(lhs.x / Math.Pow(10, moreUnit));
                lhs.y = lhs.y + moreUnit;
                if (lhs.y < 0)
                {
                    lhs.x = (float)(lhs.x * Math.Pow(10, lhs.y));
                    lhs.y = 0;   
                }     
                return lhs;
            }
            public static void Convert(ref float x,ref long y)
            {
                long moreUnit = -7;
                if (x != 0)
                    moreUnit = (long)Math.Round((Math.Log10(Math.Abs(x)) - 7));  //计算多余位
                x = (float)(x / Math.Pow(10, moreUnit));
                y = y + moreUnit;
                if (y < 0)
                {
                    x = (float)(x * Math.Pow(10, y));
                    y = 0;
                }
            }
            public static implicit operator string(Long2 obj)
            {
                return obj.ToString();
            } 
    
            /** Returns a nicely formatted string representing the vector */
            public override string ToString()
            {
                return x + "," + y ;
            } 
        }  
    }
    
    
    
    
    --%%%%%%%%  Constants used in the file %%%%%%%%--{{{1
    DEG = 10;
    LEN = 7 ;
    
    
    --%%%%%%%%        Start of Code        %%%%%%%%--
    
    BigNumber = {} ;
    BigNumber.mt = {} ;
    
    
    --BigNum.new{{{1
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    --
    --  Function: New
    --
    --
    --  Description:
    --     Creates a new Big Number based on the parameter num.
    --
    --  Parameters:
    --     num - a string, number or BigNumber.
    --
    --  Returns:
    --     A Big Number, or a nil value if an error occured.
    --
    --
    --  %%%%%%%% --
    
    function BigNumber.new( num1,num2 ) --{{{2
        local bignumber = {x=0,y=0} ;
        setmetatable( bignumber , BigNumber.mt ) ;
        if num2 == nil then
            if type(num1) == "table" then
                if num1.x == nil then
                    error("num1 结构不对")
                    return nil
                else
                    if num1.x == 0 or num1.x == "0" then
                        bignumber.x = 0;
                        bignumber.y = 0;
                    else
                        --local moreUnit = math.modf(math.log10(math.abs(num1.x)))-LEN;
                        --if moreUnit <0 then
                            --bignumber.x = 0;
                            --bignumber.y = num1.y;
                        --else
                            --bignumber.x = num1.x / math.pow(DEG,moreUnit);
                            --bignumber.y = num1.y + moreUnit; 
                        --end   
                        bignumber = BigNumber.convert(num1);
                    end 
                    return bignumber;
                end
            elseif type(num1) == "string" then
                local arr = string.split(num1,",");
                bignumber.x = tonumber(arr[1]);
                bignumber.y = tonumber(arr[2]);
                bignumber = BigNumber.convert(bignumber);
            elseif type(num1) == "number" then
                if num1 == 0 then
                    bignumber.x =0;
                    bignumber.y =0;
                else
                    bignumber.y = math.modf(math.log10(math.abs(num1)))- LEN;
                    bignumber.x = num1 / math.pow(DEG,bignumber.y);
                end
                bignumber = BigNumber.convert(bignumber);
                
            else
                error("num1 非指定类型(table、number、string),num1类型为"..type(num1));
                return  nil
            end                 
        else
            bignumber.x = tonumber(num1);
            bignumber.y = tonumber(num2);
            bignumber = BigNumber.convert(bignumber);
        end
        return bignumber ;
    end
    
    --%%%%%%%%%%%%%%%%%%%% Functions for metatable %%%%%%%%%%%%%%%%%%%%--{{{1
    --BigNum.mt.sub{{{2
    function BigNumber.mt.sub( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        bnum1 = BigNumber.sub( bnum1 , bnum2 ) ;
        return bnum1 ;
    end
    
    --BigNum.mt.add{{{2
    function BigNumber.mt.add( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        bnum1 = BigNumber.add( bnum1 , bnum2  ) ;
        return bnum1 ;
    end
    
    --BigNum.mt.mul{{{2
    function BigNumber.mt.mul( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        bnum1 = BigNumber.mul( bnum1 , bnum2  ) ;
        return bnum1 ;
    end
    
    --BigNum.mt.div{{{2
    function BigNumber.mt.div( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        bnum1 = BigNumber.div( bnum1 , bnum2 ) ;
        return bnum1 ;
    end
    
    --BigNum.mt.tostring{{{2
    function BigNumber.mt.tostring( bnum )
        return bnum.x..","..bnum.y;
    end
    
    
    
    --BigNum.mt.eq{{{2
    function BigNumber.mt.eq( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        return BigNumber.eq( bnum1 , bnum2 ) ;
    end
    
    --BigNum.mt.lt{{{2
    function BigNumber.mt.lt( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        return BigNumber.lt( bnum1 , bnum2 ) ;
    end
    
    --BigNum.mt.le{{{2
    function BigNumber.mt.le( num1 , num2 )
        local bnum1 = BigNumber.new(num1);
        local bnum2 = BigNumber.new(num2);
        return BigNumber.le( bnum1 , bnum2 ) ;
    end
    
    
    
    
    
    --%%%%%%%%%%%%%%%%%%%% Metatable Definitions %%%%%%%%%%%%%%%%%%%%--{{{1
    
    BigNumber.mt.__metatable = "hidden"           ; -- answer to getmetatable(aBignum)
    -- BigNum.mt.__index     = "inexistent field" ; -- attempt to acess nil valued field
    -- BigNum.mt.__newindex  = "not available"    ; -- attempt to create new field
    BigNumber.mt.__tostring  = BigNumber.mt.tostring ;
    -- arithmetics
    BigNumber.mt.__add = BigNumber.mt.add ;
    BigNumber.mt.__sub = BigNumber.mt.sub ;
    BigNumber.mt.__mul = BigNumber.mt.mul ;
    BigNumber.mt.__div = BigNumber.mt.div ;
    -- Comparisons
    BigNumber.mt.__eq = BigNumber.mt.eq   ;
    BigNumber.mt.__le = BigNumber.mt.le   ;
    BigNumber.mt.__lt = BigNumber.mt.lt   ;
    --concatenation
    -- BigNum.me.__concat = ???
    
    setmetatable( BigNumber.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ;
    
    --%%%%%%%%%%%%%%%%%%%% Basic Functions %%%%%%%%%%%%%%%%%%%%--{{{1
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: ADD
    --
    --
    --  Description:
    --     Adds two Big Numbers.
    --
    --  Parameters:
    --     bnum1, bnum2 - Numbers to be added.
    --     bnum3 - result
    --
    --  Returns:
    --     0
    --
    --  Exit assertions:
    --     bnum3 is the result of the sum.
    --
    --  %%%%%%%% --
    --Funcao BigNum.add{{{2
    function BigNumber.add( bnum1 , bnum2  )
        if bnum1 == nil or bnum2 == nil then
            error("Function BigNumber.add: parameter nil") ;
            return BigNumber.new()
        else
            local unit = math.max(bnum1.y,bnum2.y);
            bnum1.x = bnum1.x * math.pow(DEG,bnum1.y - unit);
            bnum1.y = unit;
            bnum2.x = bnum2.x * math.pow(DEG,bnum2.y - unit);
            bnum2.y = unit;
            bnum1.x = bnum1.x + bnum2.x;
            bnum1 = BigNumber.convert(bnum1);
            return bnum1;   
        end
    end
    
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: SUB
    --
    --
    --  Description:
    --     Subtracts two Big Numbers.
    --
    --  Parameters:
    --     bnum1, bnum2 - Numbers to be subtracted.
    --     bnum3 - result
    --
    --  Returns:
    --     0
    --
    --  Exit assertions:
    --     bnum3 is the result of the subtraction.
    --
    --  %%%%%%%% --
    --Funcao BigNum.sub{{{2
    function BigNumber.sub( bnum1 ,bnum2)
        if bnum1 == nil or bnum2 == nil then
            error("Function BigNumber.sub: parameter nil") ;
            return BigNumber.new();
        else
            local unit = math.max(bnum1.y,bnum2.y);
            bnum1.x = bnum1.x * math.pow(DEG,bnum1.y - unit);
            bnum1.y = unit;
            bnum2.x = bnum2.x * math.pow(DEG,bnum2.y - unit);
            bnum2.y = unit;
            bnum1.x = bnum1.x - bnum2.x;
            bnum1 = BigNumber.convert(bnum1);
            return bnum1;
        end
    end
    
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: MUL
    --
    --
    --  Description:
    --     Multiplies two Big Numbers.
    --
    --  Parameters:
    --     bnum1, bnum2 - Numbers to be multiplied.
    --     bnum3 - result
    --
    --  Returns:
    --     0
    --
    --  Exit assertions:
    --     bnum3 is the result of the multiplication.
    --
    --  %%%%%%%% --
    --BigNum.mul{{{2
    --can't be made in place
    function BigNumber.mul( bnum1 , bnum2 )
        if bnum1 == nil or bnum2 == nil then
            error("Function BigNumber.mul: parameter nil") ;
            return BigNumber.new();
        else
            bnum1.x = bnum1.x * bnum2.x;
            if bnum1.x == 0 then
                return BigNumber.new();
            end
            bnum1.y = bnum1.y + bnum2.y;
            bnum1 = BigNumber.convert(bnum1);
            return bnum1; 
        end
    end
    
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: DIV
    --
    --
    --  Description:
    --     Divides bnum1 by bnum2.
    --
    --  Parameters:
    --     bnum1, bnum2 - Numbers to be divided.
    --     bnum3 - result
    --     bnum4 - remainder
    --
    --  Returns:
    --     0
    --
    --  Exit assertions:
    --     bnum3 is the result of the division.
    --     bnum4 is the remainder of the division.
    --
    --  %%%%%%%% --
    --BigNum.div{{{2
    function BigNumber.div( bnum1 , bnum2)
        if bnum1 == nil or bnum2 == nil  then
            error( "Function BigNumber.div: parameter nil" ) ;
            return BigNumber.new();
        else
            bnum1.x = bnum1.x / bnum2.x;
            if bnum1.x == 0 then
                return  BigNumber.new();
            end
            bnum1.y = bnum1.y - bnum2.y; 
            bnum1 = BigNumber.convert(bnum1);
            return  bnum1;
        end
    end
    
    --%%%%%%%%%%%%%%%%%%%% Compound Functions %%%%%%%%%%%%%%%%%%%%--{{{1
    
    
    
    
    
    --%%%%%%%%%%%%%%%%%%%% Comparison Functions %%%%%%%%%%%%%%%%%%%%--{{{1
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: EQ
    --
    --
    --  Description:
    --     Compares two Big Numbers.
    --
    --  Parameters:
    --     bnum1, bnum2 - numbers
    --
    --  Returns:
    --     Returns true if they are equal or false otherwise.
    --
    --  %%%%%%%% --
    --BigNum.eq{{{2
    function BigNumber.eq( bnum1 , bnum2 )
        if BigNumber.compare( bnum1 , bnum2 ) == 0 then
            return true ;
        else
            return false ;
        end
    end
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: LT
    --
    --
    --  Description:
    --     Verifies if bnum1 is lesser than bnum2.
    --
    --  Parameters:
    --     bnum1, bnum2 - numbers
    --
    --  Returns:
    --     Returns true if bnum1 is lesser than bnum2 or false otherwise.
    --
    --  %%%%%%%% --
    --BigNum.lt{{{2
    function BigNumber.lt( bnum1 , bnum2 )
        if BigNumber.compare( bnum1 , bnum2 ) == 2 then
            return true ;
        else
            return false ;
        end
    end
    
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: LE
    --
    --
    --  Description:
    --     Verifies if bnum1 is lesser or equal than bnum2.
    --
    --  Parameters:
    --     bnum1, bnum2 - numbers
    --
    --  Returns:
    --     Returns true if bnum1 is lesser or equal than bnum2 or false otherwise.
    --
    --  %%%%%%%% --
    --BigNum.le{{{2
    function BigNumber.le( bnum1 , bnum2 )
        local temp = -1 ;
        temp = BigNumber.compare( bnum1 , bnum2 )
        if temp == 0 or temp == 2 then
            return true ;
        else
            return false ;
        end
    end
    
    
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    --
    --  Function: Compare
    --
    --
    --  Description:
    --     Compares values of bnum1 and bnum2.
    --
    --  Parameters:
    --     bnum1, bnum2 - numbers
    --
    --  Returns:
    --     1 - |bnum1| > |bnum2|
    --     2 - |bnum1| < |bnum2|
    --     0 - |bnum1| = |bnum2|
    --
    --  %%%%%%%% --
    --BigNum.compare{{{2
    function BigNumber.compare( bnum1 , bnum2 )
        --1是大于,2是小于,0是等于
        if bnum1 == nil or bnum2 == nil then
            error("Funtion BigNum.compare: parameter nil") ;
            return 3;
        else
            
            local l = bnum1-bnum2;
            if math.abs(l.x) <=0.01 then
                return 0;
            elseif l.x >0.01 then
                return 1;   
            else 
                return 2;
            end     
        end
    end
    
    
    
    
    
    --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
    
    
    function BigNumber.convert( num)
        local bnum = {};
        setmetatable( bnum , BigNumber.mt ) ;
        local moreUnit = -LEN;
        if num.x ~= 0 or num.x ~= -0 then
            moreUnit = math.modf(math.log10(math.abs(num.x))) - LEN;
        end
        bnum.x = num.x / math.pow(DEG,moreUnit);
        bnum.y = num.y + moreUnit;
        if bnum.y <0 then
            bnum.x = bnum.x * math.pow(DEG,bnum.y);
            bnum.y = 0;
        end
        return bnum;
    end
    
    
    
    
    

    相关文章

      网友评论

          本文标题:Unity 放置类大数据

          本文链接:https://www.haomeiwen.com/subject/cuowrltx.html