Unity 放置类大数据

目前常用的数据类型

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




最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容