目前常用的数据类型
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打印的结果,各个数据类型所占字节数以及最大、最小值
- 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最终输出结果是多少呢?
这是什么原因呢?这是因为浮点数超过七位数(包括小数位),计算精度会降低,将会出现上面的结果;那是否意味着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的异常。
下面看看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