目前常用的數(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ù)以及最大、最小值
- 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é)果是多少呢?
這是什么原因呢红淡?這是因?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的異常惰蜜。
下面看看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