Unity 放置類大數(shù)據(jù)

目前常用的數(shù)據(jù)類型

sbyte八位有符號(hào)整數(shù) -128~127
byte八位無(wú)符號(hào)整數(shù) 0~255
short十六位無(wú)符號(hào)整數(shù) 0~65535

  • int三十二位有符號(hào)整數(shù) -214783648~214783647
    unit三十二位無(wú)符號(hào)整數(shù) 0~4294967295
  • long六十四位有符號(hào)整數(shù) -9223372036854775808~9223372036854775807
    ulong六十四為無(wú)符號(hào)整數(shù) 0~18446744073709551615
    char十六位字符類型 所有Unicode編碼字符
  • float三十二單精度浮點(diǎn)類型 大約七個(gè)有效十進(jìn)制數(shù)位
  • double六十四位雙精度浮點(diǎn)類型 大約15~16個(gè)有效十進(jìn)制數(shù)
    decimal一百二十八位高精度十進(jìn)制數(shù)類型 大約28~29有效十進(jìn)制數(shù)位

在項(xiàng)目中大家可能比較常用的是int long float double

下圖是在unity打印的結(jié)果,各個(gè)數(shù)據(jù)類型所占字節(jié)數(shù)以及最大、最小值


image.png
  • float和int類型同樣是占有32位,為什么float能存儲(chǔ)3.402823E+38
    機(jī)器不會(huì)騙人阴挣,原因就是它不是按int這么存數(shù)據(jù)的。比如一個(gè)float 數(shù)據(jù)
    1024.1024 等價(jià)于 1.0241024 * 10^3 (3表示指數(shù)摸柄,1.0241024表示有效數(shù)字)float其實(shí)只是把符號(hào)骚秦、指數(shù)、有效數(shù)字3部分保存脯厨,真正在運(yùn)算的時(shí)候是根據(jù)指數(shù)在移位操作铅祸。
    float把 32位分成了3部分,1位(符號(hào)位)8位(指數(shù)位)23位(有效數(shù)字)那么 1+ 8 + 23 等于32吧合武,所以float的32位是這么來(lái)的临梗。23位有效數(shù)字就表示float真正能存的精度,23位小數(shù)部分是反被儲(chǔ)存的部分稼跳,所以它是有24位存儲(chǔ)的盟庞,2^24(2的24次方)=16777216,下面做個(gè)試驗(yàn)
        float a = 1658459f;
        float b = a + 0.1f;
        Debug.Log($"a={a},b=汤善");

定義a=1658459f,b=a+0.1f,想想a什猖、b最終輸出結(jié)果是多少呢?


image.png

這是什么原因呢红淡?這是因?yàn)楦↑c(diǎn)數(shù)超過(guò)七位數(shù)(包括小數(shù)位)不狮,計(jì)算精度會(huì)降低,將會(huì)出現(xiàn)上面的結(jié)果在旱;那是否意味著a=b呢荤傲?答案是NO,只能是近似相等颈渊。

float我們介紹完了遂黍,double的原理和float差不多,double占8字節(jié)俊嗽,1位符號(hào)位+11位指數(shù)+52位有效數(shù)字 = 64位雾家。double的有效2^53(2的53次方)=9007199254740992,超過(guò)9007199254740992.xxx那么很抱歉它們的結(jié)果是一致的绍豁。

而且浮點(diǎn)數(shù)計(jì)算結(jié)果不同的CPU計(jì)算出來(lái)可能是不一致的芯咧,像幀同步那種游戲基本應(yīng)該告別float和double了。例如iphone對(duì)浮點(diǎn)型計(jì)算就比較弱竹揍。

最后我們?cè)诹囊幌露c(diǎn)數(shù)敬飒,應(yīng)對(duì)解決精度問(wèn)題,c#提供了定點(diǎn)數(shù)decimal關(guān)鍵字芬位∥揶郑可以看到它是由16個(gè)字節(jié)組成也就是128位,內(nèi)存大小相當(dāng)于4個(gè)float或者2個(gè)double 取值范圍也很高昧碉。
1-12字節(jié):它先用前12個(gè)字節(jié)來(lái)表示定點(diǎn)數(shù)數(shù)據(jù)英染,1字節(jié)8位揽惹,12個(gè)字節(jié)就是8*12 =96位,那么它的取值范圍就是2^96(2的96次方)7.922816251426E+28
13-15字節(jié):在用3個(gè)字節(jié)來(lái)表示指數(shù)
16字節(jié):最后一個(gè)字節(jié)來(lái)表示符號(hào)
只要數(shù)據(jù)在10進(jìn)制28-29位之間四康,小數(shù)點(diǎn)在中間任意位置均可搪搏。數(shù)據(jù)運(yùn)算就不會(huì)像float和double一樣被和諧了。所以說(shuō)如果需要準(zhǔn)確精度的小數(shù)計(jì)算就一定要使用定點(diǎn)數(shù)闪金。

double(雙精度浮點(diǎn))類型最大值為1.79769313486232E+308疯溺,我們一下主要用double于咱們自己定義數(shù)據(jù)類型做比較。

放置類幾種常用數(shù)值比較

一般做放置類型游戲哎垦,數(shù)據(jù)是比較大的喝检,你永遠(yuǎn)不知道策劃大佬的數(shù)值有多大,我們?cè)趺茨軡M足策劃大佬的需求呢撼泛?double可能在大多數(shù)情況下能滿足策劃大佬需求,雖然有的策劃說(shuō)我的數(shù)值表里面數(shù)值不會(huì)超過(guò)double的最大值澡谭,但誰(shuí)能保證玩家的金錢不會(huì)越界呢愿题?希望大家都能把玩家基數(shù)想的足夠大,幾百萬(wàn)蛙奖,上千萬(wàn)甚至過(guò)億潘酗,夢(mèng)想總是要有的,萬(wàn)一實(shí)現(xiàn)了呢雁仲,大家的小目標(biāo)還會(huì)遠(yuǎn)嗎仔夺?嘿嘿

我想閱讀到這里就會(huì)有同學(xué)提出BigInteger超大整型數(shù)字
BigInteger
自.net framework 4.0開始引入, 位于命名空間:

namespace System.Numerics

設(shè)計(jì)用于存儲(chǔ)超大整型數(shù)字攒砖,所以只要內(nèi)存夠大缸兔,存儲(chǔ)是沒有上限和下限的,否則如果數(shù)字過(guò)大的話吹艇,會(huì)遇到OutOfMemory的異常惰蜜。


image.png

下面看看BigInteger的運(yùn)算
加:bi1.add(bi2)
減:bi1.subtract(bi2)
乘:bi1.multiply(bi2)
除: bi1.divide(bi2)
取余:bi1.remainder(bi2)
是不是和我們常用的值類型加、減受神、乘抛猖、除不太一樣
我們?cè)倩仡^看看BigInteger的定義超大整型數(shù)字整型劃重點(diǎn)鼻听,一會(huì)要考财著。
如果咱們用整型,策劃大佬會(huì)答應(yīng)嗎撑碴?能滿足小數(shù)的需求么撑教?一毛錢不是錢么,日積月累定能超過(guò)一塊錢醉拓。
Q:那如果說(shuō)前期用double類型后期再把double類型換成BigInteger類型驮履,反正double類型超過(guò)7位數(shù)計(jì)算精度也不準(zhǔn)確鱼辙,判斷超過(guò)7位數(shù)就轉(zhuǎn)成BigInteger,此時(shí)小數(shù)點(diǎn)后面數(shù)字相對(duì)于百萬(wàn)幾乎可以忽略不計(jì)(放置類數(shù)值精度也沒要求那么準(zhǔn)確)
A:我只想說(shuō)累不玫镐?用兩種類型轉(zhuǎn)換倒戏;那如果A=1E+8用BigInteger類型存儲(chǔ),B=1E+6用double類型存儲(chǔ)恐似,A和B的加杜跷、減、乘矫夷、除葛闷,我們又當(dāng)如何計(jì)算呢?

Double最大值為1.79769313486232E+308双藕,基本上能滿足策劃大佬的數(shù)據(jù)要求淑趾,但作為開發(fā)人員做技術(shù)要嚴(yán)謹(jǐn),為了能滿足大數(shù)據(jù)需求忧陪,防止廣大用戶數(shù)據(jù)越界扣泊,我自定義一個(gè)數(shù)據(jù)類型Long2,下面講下這個(gè)數(shù)據(jù)類型的設(shè)計(jì)思路嘶摊。

自定義大數(shù)據(jù)類型

設(shè)計(jì)思路基于科學(xué)計(jì)算法
定于兩個(gè)變量延蟹,float類型變量x作為計(jì)數(shù),long類型變量y作為10的指數(shù)(單位)叶堆,x數(shù)值最大不超過(guò)8位正數(shù)阱飘;

1.假設(shè)有個(gè)數(shù)值A=124534563812347524204534轉(zhuǎn)換成Long2類型,先求出y虱颗,y=INT(LOG(A)-7)=16;x=A/(10^y)=12453456.381(保留三位小數(shù))沥匈;最終我們計(jì)算出long1=12453456.381,16
2.另一個(gè)數(shù)值B=78541124634534535247454轉(zhuǎn)換成Long2類型,按第一步先求出y=INT(LOG(B)-7)=15忘渔;x=B/(10^y)=78541124.635(保留三位小數(shù))咐熙;最終我們計(jì)算出long2 = 78541124.635,15
下面計(jì)算A、B的加減乘除
A+B 辨萍、A-B

  • 帶有指數(shù)數(shù)字的相加或者相減要保持指數(shù)一樣
    咱們轉(zhuǎn)換下棋恼,long1=12453456.381,16 long2=7854112.463,16
    加法最終結(jié)果為:20307568.844,16
    減法最終結(jié)果為:4599343.918,16
    AxB
    long1計(jì)數(shù)x1乘以long2計(jì)數(shù)x2,計(jì)數(shù)想成結(jié)果為x=x1x2=9.781E+14锈玉,發(fā)現(xiàn)是大于八位數(shù)的爪飘,此時(shí)我們需要對(duì)計(jì)數(shù)想成結(jié)果做次單位轉(zhuǎn)換計(jì)算出多余位數(shù)moreY = INT(LOG10(x)-7); x=x/(10^moreY)=97810843;最終的y應(yīng)該等于long1的y1加long2*的y2加多余位數(shù),y=y1+y2+moreY = 38;最終結(jié)果為97810843拉背,38
    A/B
    x=x1/x2=0.15855969师崎,計(jì)算出多余位數(shù)moreY = INT(LOG10(x)-7) = -8;x= x/(10^moreY) = 15855968;y = y1-y2+moreY = -7;最終結(jié)果為15855968椅棺,-7

備注:目前沒看到內(nèi)存修改器可以修改此類型數(shù)據(jù)

下面貼出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);  //計(jì)算多余位
                    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);  //計(jì)算多余位
            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);  //計(jì)算多余位
            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));  //計(jì)算多余位
            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));  //計(jì)算多余位
            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));  //計(jì)算多余位
            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);  //計(jì)算多余位
            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($"被除數(shù)為零");
                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));  //計(jì)算多余位   
            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($"被除數(shù)為零");
                return lhs;
            }
            float hs = lhs.x / rhs;
            if (hs == 0)
                return Long2.zero;
            long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //計(jì)算多余位
            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($"被除數(shù)為零");
                return lhs;
            }
            float hs = lhs.x / rhs;
            if (hs == 0)
                return Long2.zero;
            long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //計(jì)算多余位
            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($"被除數(shù)為零");
                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));  //計(jì)算多余位
            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($"被除數(shù)為零");
                return lhs;
            }
            float hs = lhs.x / rhs;
            if (hs == 0)
                return Long2.zero;
            long moreUnit = (long)Math.Round((Math.Log10(Math.Abs(hs)) - 7));  //計(jì)算多余位
            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));  //計(jì)算多余位
            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));  //計(jì)算多余位
            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 結(jié)構(gòu)不對(duì)")
                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




最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市床估,隨后出現(xiàn)的幾起案子含滴,更是在濱河造成了極大的恐慌,老刑警劉巖丐巫,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谈况,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡递胧,警方通過(guò)查閱死者的電腦和手機(jī)碑韵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缎脾,“玉大人祝闻,你說(shuō)我怎么就攤上這事∫挪ぃ” “怎么了联喘?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)舷蒲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)友多,這世上最難降的妖魔是什么牲平? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮域滥,結(jié)果婚禮上纵柿,老公的妹妹穿的比我還像新娘。我一直安慰自己启绰,他們只是感情好昂儒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著委可,像睡著了一般渊跋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上着倾,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天拾酝,我揣著相機(jī)與錄音,去河邊找鬼卡者。 笑死蒿囤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的崇决。 我是一名探鬼主播材诽,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼底挫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了脸侥?” 一聲冷哼從身側(cè)響起建邓,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎湿痢,沒想到半個(gè)月后涝缝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡譬重,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年拒逮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臀规。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡滩援,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出塔嬉,到底是詐尸還是另有隱情玩徊,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布谨究,位于F島的核電站恩袱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胶哲。R本人自食惡果不足惜畔塔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸯屿。 院中可真熱鬧澈吨,春花似錦、人聲如沸寄摆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)婶恼。三九已至桑阶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間勾邦,已是汗流浹背联逻。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留检痰,地道東北人包归。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像铅歼,于是被迫代替她去往敵國(guó)和親公壤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子换可,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容